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