Home | History | Annotate | Download | only in clisrv
      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
     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 
     56 int str_echo(sockfd)
     57 int sockfd;
     58 {
     59 	int n, testint;
     60 	char line[MAXLINE];
     61 
     62 	printf("sockfd = %d\n", sockfd);
     63 	for (;;) {
     64 		prtln();
     65 		dprt2(("%s: str_echo(): reading from sockfd %d\n", __FILE__,
     66 		       sockfd));
     67 		n = readline(sockfd, line, MAXLINE);
     68 		printf("str_echo: n = %d\n", n);
     69 		if (n == 0) {
     70 			dprt2(("%s: str_echo(): connection terminated\n",
     71 			       __FILE__));
     72 			return 0;	/* connection terminated */
     73 		} else if (n < 0) {
     74 			perror("str_echo: readline error");
     75 			return (-1);
     76 		}
     77 		dprt2(("%s: str_echo(): writing to sockfd = %d\n", __FILE__,
     78 		       sockfd));
     79 		testint = writen(sockfd, line, n);
     80 		prtln();
     81 		if (testint != n) {
     82 			perror("str_echo: writen error");
     83 			return (-1);
     84 		}
     85 		prtln();
     86 	}
     87 }
     88 
     89 int main(int argc, char *argv[])
     90 {
     91 	void *new_thread(void *);
     92 	pthread_attr_t newattr;
     93 	int newsockfd;
     94 	socklen_t clilen;
     95 	struct sockaddr_in cli_addr, serv_addr;
     96 	pname = argv[0];
     97 
     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 
    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