• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&current_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(&current_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(&current_mutex))
176 		printf("mutex_unlock failed");
177 #ifndef _LINUX
178 	yield();
179 #else
180 	sched_yield();
181 #endif
182 	pthread_exit(NULL);
183 }
184