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