1    | /***************************************
2    |   $Revision: 1.3 $
3    | 
4    |   Example code: A thread.
5    | 
6    |   Status: NOT REVUED, NOT TESTED
7    | 
8    |  Authors:       Chris Ottrey
9    | 		Joao Damas
10   | 
11   |   +html+ <DL COMPACT>
12   |   +html+ <DT>Online References:
13   |   +html+ <DD><UL>
14   |   +html+ </UL>
15   |   +html+ </DL>
16   |  
17   |   ******************/ /******************
18   |   Modification History:
19   |         ottrey (02/03/1999) Created.
20   |         ottrey (08/03/1999) Modified.
21   |         ottrey (17/06/1999) Stripped down.
22   |         joao   (22/06/1999) Redid thread startup
23   |   ******************/ /******************
24   |   Copyright (c) 1999                              RIPE NCC
25   |  
26   |   All Rights Reserved
27   |   
28   |   Permission to use, copy, modify, and distribute this software and its
29   |   documentation for any purpose and without fee is hereby granted,
30   |   provided that the above copyright notice appear in all copies and that
31   |   both that copyright notice and this permission notice appear in
32   |   supporting documentation, and that the name of the author not be
33   |   used in advertising or publicity pertaining to distribution of the
34   |   software without specific, written prior permission.
35   |   
36   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
37   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
38   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
39   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
40   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
41   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42   |   ***************************************/
43   | #include <stdio.h>
44   | #include <pthread.h>       /* Posix thread library */
45   | #include "protocol_config.h"
46   | #include "constants.h"
47   | 
48   | /*+ String sizes +*/
49   | #define STR_S   63
50   | #define STR_M   255
51   | #define STR_L   1023
52   | #define STR_XL  4095
53   | #define STR_XXL 16383
54   | 
55   | /*+ Mutex lock.  Used for synchronizing changes. +*/
56   | pthread_mutex_t   Whois_thread_count_lock;
57   | pthread_mutex_t   Config_thread_count_lock;
58   | pthread_mutex_t   Mirror_thread_count_lock;
59   | 
60   | /*+ The number of threads. +*/
61   | int       Whois_thread_count;
62   | int       Config_thread_count;
63   | int       Mirror_thread_count;
64   | 
65   | typedef struct th_args {
66   | 	void * function;
67   | 	int sock;
68   | 	} th_args;
69   | 
70   | static void log_print(const char *arg) {
71   |   FILE *logf;
72   |   char *str;
73   | 
74   |   if (CO_get_thread_logging() == 1) {
75   |     if (strcmp(CO_get_thread_logfile(), "stdout") == 0) {
76   |       printf(arg);
77   |     }
78   |     else {
79   |       logf = fopen(CO_get_thread_logfile(), "a");
80   |       fprintf(logf, arg);
81   |       fclose(logf);
82   |     }
83   |   }
84   | 
85   | } /* log_print() */
86   |  
87   | int TH_get_id(void) {
88   | 
89   |   return (int)pthread_self();
90   | 
91   | } /* TH_get_id() */
92   | 
93   | /* TH_to_string() */
94   | char *TH_to_string(void) {
95   |   char *thread_info;
96   |   char tmp[STR_L];
97   |   char thread_info_buffer[STR_XL];
98   |   char *thread_name;
99   | 
100  |   strcpy(thread_info_buffer, "Thread = { ");
101  | 
102  |   sprintf(tmp, "[pthread_self] = \"%d\" ", pthread_self());
103  |   strcat(thread_info_buffer, tmp);
104  |   
105  |   /*
106  |   thread_name = (char *)pthread_getspecific(Name);
107  | 
108  |   if (thread_name == NULL ) {
109  |     sprintf(tmp, "[Name] = \"%s\" ", "didn't work!");
110  |   }
111  |   else {
112  |     sprintf(tmp, "[Name] = \"%s\" ", thread_name);
113  |   }
114  |   strcat(thread_info_buffer, tmp);
115  |   */
116  |   
117  |   strcat(thread_info_buffer, "}");
118  |   
119  |   thread_info = (char *)calloc(1, strlen(thread_info_buffer)+1);
120  |   strcpy(thread_info, thread_info_buffer);
121  | 
122  |   return thread_info;
123  | } /* TH_to_string() */
124  | 
125  | /* TH_do_whois() */
126  | /*++++++++++++++++++++++++++++++++++++++
127  | 
128  |   Handle whois connections.
129  | 
130  |   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
131  | 
132  |   More:
133  |   +html+ <PRE>
134  |   Author:
135  |         joao
136  |   +html+ </PRE>
137  |   ++++++++++++++++++++++++++++++++++++++*/
138  | void TH_do_whois(void *arg) { 
139  |   int sock = (int)arg;
140  |   char print_buf[STR_M];
141  | 
142  |   sprintf(print_buf, "Whois: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
143  | 
144  |   /* Use a mutex to update the global whois thread counter. */
145  |   pthread_mutex_lock(&Whois_thread_count_lock);
146  |   Whois_thread_count++;
147  |   sprintf(print_buf, "Whois_thread_count++=%d\n", Whois_thread_count); log_print(print_buf); strcpy(print_buf, "");
148  |   pthread_mutex_unlock(&Whois_thread_count_lock);
149  | 
150  |   PW_interact(sock);
151  | 
152  |   /* Use a mutex to update the global whois thread counter. */
153  |   pthread_mutex_lock(&Whois_thread_count_lock);
154  |   Whois_thread_count--;
155  |   sprintf(print_buf, "Whois_thread_count--=%d\n", Whois_thread_count); log_print(print_buf); strcpy(print_buf, "");
156  |   pthread_mutex_unlock(&Whois_thread_count_lock);
157  | 
158  |   pthread_exit((void *)0);
159  | 
160  | } /* TH_do_whois() */
161  | 
162  | /* TH_do_config() */
163  | /*++++++++++++++++++++++++++++++++++++++
164  | 
165  |   Handle config connections.
166  | 
167  |   void *arg The socket to connect to. (It has to be passed in this way for this
168  | thread routine.)
169  | 
170  |   More:
171  |   +html+ <PRE>
172  |   Author:
173  |         joao
174  |   +html+ </PRE>
175  |   ++++++++++++++++++++++++++++++++++++++*/
176  | void TH_do_config(void *arg) {
177  |   int sock = (int)arg;
178  |   char print_buf[STR_M];
179  | 
180  |   sprintf(print_buf, "Config: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
181  | 
182  | /*
183  |   printf("Hi there, there is nothing to configure yet\nBye..... :-)\n");
184  |   fflush(NULL);
185  | 
186  |   SK_close(sock);
187  | */
188  |   PC_interact(sock);
189  | 
190  |   pthread_exit((void *)0);
191  | 
192  | } /* TH_do_config() */
193  | 
194  | /* main_function() */
195  | /*++++++++++++++++++++++++++++++++++++++
196  | 
197  |   Waits for an incoming connection on the and spawns a new thread to handle it.
198  | 
199  |   void *arg Pointer to a struct containing the socket to talk to the client and
200  |             the function to call depending on the incoming connection.
201  | 
202  |   More:
203  |   +html+ <PRE>
204  |   Author:
205  |         ottrey
206  | 	joao
207  |   +html+ </PRE>
208  |   ++++++++++++++++++++++++++++++++++++++*/
209  | static void  *main_thread(void *arg) {
210  |   th_args *args = (th_args *)arg;
211  |   pthread_t tid;
212  |   pthread_attr_t attr;
213  |   int connected_socket;
214  | 
215  |   while(1) {
216  | 
217  |     connected_socket = SK_accept_connection(args->sock);
218  | 
219  |     /* Start a new thread. */
220  | 
221  |     pthread_attr_init(&attr);    /* initialize attr with default attributes */
222  |     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
223  |     pthread_create(&tid, &attr, (void *(*)(void *))(args->function), (void *)connected_socket); 
224  |   }
225  | 
226  | } /* main_function() */
227  | 
228  | /* TH_run() */
229  | /*++++++++++++++++++++++++++++++++++++++
230  | 
231  |   This is the routine that creates the main threads. 
232  | 
233  |   int     sock        The socket to connect to.
234  |   void *  do_function The function to call for each type of service
235  | 
236  |   More:
237  |   +html+ <PRE>
238  |   Author:
239  |         ottrey
240  | 	joao
241  |   +html+ </PRE>
242  |   ++++++++++++++++++++++++++++++++++++++*/
243  | void TH_run(int sock, void *do_function) {
244  |   th_args *args;
245  |   pthread_t tid;
246  |   pthread_attr_t attr;
247  |   char print_buf[STR_M];
248  | 
249  |   int connected_socket;
250  | 
251  |   args = (th_args *)calloc(1,sizeof(th_args));
252  |   args->function=do_function;
253  |   args->sock=sock;
254  | 
255  | /*  pthread_mutex_init(&Whois_thread_count_lock,NULL); */
256  | 
257  |   if ( CO_get_max_threads() == 0 ) {
258  |     sprintf(print_buf, "Running with no threads\n"); log_print(print_buf); strcpy(print_buf, "");
259  |     connected_socket = SK_accept_connection(sock);
260  |     PW_interact(connected_socket);
261  |   }
262  |   else {
263  |     /* Start a new thread. */
264  |     pthread_attr_init(&attr);     /* initialize attr with default attributes */
265  |     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
266  |     pthread_create(&tid, &attr, main_thread, (void *)args);
267  |   }
268  | 
269  | } /* TH_run() */