1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2001-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 /* to test multiple threads in ei */
22 
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 
27 #ifdef __WIN32__
28 #include <winsock2.h>
29 #include <windows.h>
30 #include <process.h>
31 #else
32 #include <pthread.h>
33 #include <sys/socket.h>
34 #include <unistd.h>
35 #endif
36 
37 #include "ei.h"
38 
39 /*
40    A small einode.
41    To be called from the test case ei_accept_SUITE:multi_thread
42    usage: einode <cookie> <n> <destnode>
43 
44    - start threads 0..n-1
45    - in each thread
46       - connect to destnode
47       - send a message ("ei0".."ei<n-1>") to mth0..mth<n-1> on destnode
48       - shutdown gracefully
49 */
50 
51 static const char* cookie, * desthost;
52 
53 #ifndef SD_SEND
54 #ifdef SHUTWR
55 #define SD_SEND SHUT_WR
56 #else
57 #define SD_SEND 1
58 #endif
59 #endif
60 
61 #ifndef __WIN32__
62 #define closesocket(fd) close(fd)
63 #endif
64 
65 #ifdef __WIN32__
66 static DWORD WINAPI
67 #else
68 static void*
69 #endif
einode_thread(void * num)70     einode_thread(void* num)
71 {
72     int n = (int)num;
73     ei_cnode ec;
74     char myname[100], destname[100];
75     int r, fd;
76 
77     sprintf(myname, "ei%d", n);
78     sprintf(destname, "mth%d", n);
79     printf("thread %d (%s %s) connecting\n", n, myname, destname);
80     r = ei_connect_init(&ec, myname, cookie, 0);
81     fd = ei_connect(&ec, (char*)desthost);
82     if (r == 0 && fd >= 0) {
83 	ei_x_buff x;
84 	ei_x_new_with_version(&x);
85 	ei_x_encode_string(&x, myname);
86 	ei_reg_send(&ec, fd, destname, x.buff, x.index);
87 	ei_x_free(&x);
88 	//SleepEx(100);
89 	shutdown(fd, SD_SEND);
90 	closesocket(fd);
91     } else {
92 	printf("coudn't connect fd %d r %d\n", fd, r); //	DebugBreak();
93     }
94     printf("done thread %d\n", n);
95     return 0;
96 }
97 
main(int argc,char * argv[])98 int main(int argc, char *argv[])
99 {
100     int i, n, no_threads;
101 #ifdef __WIN32__
102     HANDLE threads[100];
103 #else
104     pthread_t threads[100];
105 #endif
106 
107     if (argc < 3)
108 	exit(1);
109 
110     ei_init();
111 
112     cookie = argv[1];
113     n = atoi(argv[2]);
114     if (n > 100)
115 	exit(2);
116     desthost = argv[3];
117     no_threads = argv[4] != NULL && strcmp(argv[4], "nothreads") == 0;
118     for (i = 0; i < n; ++i) {
119 	if (!no_threads) {
120 #ifdef __WIN32__
121 	    unsigned tid;
122 	    threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread,
123 						(void*)i, 0, &tid);
124 #else
125 	    pthread_create(&threads[i], NULL, einode_thread, (void*)i);
126 #endif
127 	} else
128 	    einode_thread((void*)i);
129     }
130     if (!no_threads)
131 	for (i = 0; i < n; ++i) {
132 #ifdef __WIN32__
133 	    if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0)
134 #else
135 	    if (pthread_join(threads[i], NULL) != 0)
136 #endif
137 		printf("bad wait thread %d\n", i);
138 	}
139     printf("ok\n");
140     return 0;
141 }
142