1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 /*
19 * File: pthserv.c Version: 1.3 Last update: 5/19/94 08:55:35
20 */
21 /******************************************************************************/
22 /* File: pthserv.c */
23 /* */
24 /* Description: Read a stream socket one line at a time and write each line */
25 /* back to the sender. */
26 /* */
27 /* History: Contact - 06/21/2001 - Manoj Iyeri, IBM Austin */
28 /* */
29 /* Usage: pthcli [port number] */
30 /* */
31 /******************************************************************************/
32
33 /*
34 TCP server
35 */
36
37 #include <pthread.h>
38 #include <string.h>
39 #include "inet.h"
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <stdint.h>
43
44 #define MAXLINE 1024
noprintf(char * string,...)45 void noprintf(char *string, ...)
46 {
47 }
48
49 pthread_t th;
50 pthread_mutex_t current_mutex;
51 int sockfd;
52
53 /* Read a stream socket one line at a time and write each line back
54 to sender. Return when connection is terminated */
55
str_echo(int sockfd)56 int str_echo(int sockfd)
57 {
58 int n, testint;
59 char line[MAXLINE];
60
61 printf("sockfd = %d\n", sockfd);
62 for (;;) {
63 prtln();
64 dprt2(("%s: str_echo(): reading from sockfd %d\n", __FILE__,
65 sockfd));
66 n = readline(sockfd, line, MAXLINE);
67 printf("str_echo: n = %d\n", n);
68 if (n == 0) {
69 dprt2(("%s: str_echo(): connection terminated\n",
70 __FILE__));
71 return 0; /* connection terminated */
72 } else if (n < 0) {
73 perror("str_echo: readline error");
74 return (-1);
75 }
76 dprt2(("%s: str_echo(): writing to sockfd = %d\n", __FILE__,
77 sockfd));
78 testint = writen(sockfd, line, n);
79 prtln();
80 if (testint != n) {
81 perror("str_echo: writen error");
82 return (-1);
83 }
84 prtln();
85 }
86 }
87
main(int argc,char * argv[])88 int main(int argc, char *argv[])
89 {
90 void *new_thread(void *);
91 pthread_attr_t newattr;
92 int newsockfd;
93 socklen_t clilen;
94 struct sockaddr_in cli_addr, serv_addr;
95 pname = argv[0];
96
97 (void) argc;
98 prtln();
99 /* Open inet stream socket */
100 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
101 printf("server: socket failure:");
102 exit(1);
103 }
104 prtln();
105 dprt2(("%s: main(): Open inet stream socket sockfd = %d\n", __FILE__,
106 sockfd));
107
108 /* Bind local address for client to use */
109 memset((char *)&serv_addr, 0x00, sizeof(serv_addr));
110 serv_addr.sin_family = AF_INET;
111 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
112 serv_addr.sin_port = htons(SERV_TCP_PORT);
113 prtln();
114 dprt2(("%s: main(): Binding local address for client to use\n"
115 "serv_addr.sin_family = %d\n serv_addr.sin_addr.s_addr = %#x\n"
116 "serv_addr.sin_port = %d\n", __FILE__, serv_addr.sin_family,
117 serv_addr.sin_addr.s_addr, serv_addr.sin_port));
118
119 prtln();
120 if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
121 printf("server bind failure:\n");
122 fflush(NULL);
123 exit(1);
124 }
125
126 prtln();
127 if (pthread_mutex_init(¤t_mutex, NULL) != 0)
128 printf("current_mutex_init() failure");
129 prtln();
130
131 /* attr init, detached state create thread */
132 if (pthread_attr_init(&newattr))
133 printf("failure to init attributes\n");
134 if (pthread_attr_setdetachstate(&newattr, PTHREAD_CREATE_DETACHED))
135 printf("failure to set detached state\n");
136 prtln();
137 listen(sockfd, 5);
138
139 prtln();
140 for (;;) {
141 /* Wait for connection from a client process */
142 clilen = sizeof(cli_addr);
143
144 newsockfd =
145 accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
146 prtln();
147 if (newsockfd < 0) {
148 perror("server: accept");
149 printf("server: accept error");
150 exit(1);
151 } else { /* create thread to handle client request */
152
153 if (pthread_create(&th, &newattr, new_thread,
154 (void *)(uintptr_t) newsockfd))
155 printf("failure to create thread\n");
156 #ifndef _LINUX
157 yield();
158 #else
159 sched_yield();
160 #endif
161 }
162 prtln();
163 }
164 close(sockfd);
165 }
166
new_thread(void * arg_)167 void *new_thread(void *arg_)
168 {
169 int arg = (uintptr_t) arg_;
170 if (pthread_mutex_lock(¤t_mutex))
171 printf("mutex_lock failed");
172 if (str_echo(arg) < 0) /* process the request */
173 printf("new_thread: str_echo returned error");
174 close(arg); /* i.e. newsockfd */
175 if (pthread_mutex_unlock(¤t_mutex))
176 printf("mutex_unlock failed");
177 #ifndef _LINUX
178 yield();
179 #else
180 sched_yield();
181 #endif
182 pthread_exit(NULL);
183 }
184