Česky
Kamil Dudka

Tiny programs (C, C++, C#, ...)

File detail

Name:Downloadtcp_client.c [Download]
Location: tiny > ISA > nntpbackup
Size:3.7 KB
Last modification:2022-09-09 13:06

Source code

/*
 * file: net_client.c - TCP layer encapsulation
 * project: nntpbackup (ISA)
 * By Kamil Dudka, xdudka00
 * mailto: xdudka00@gmail.com
 * Note: This modul was primarily developed for project BSD sockets (IPK)
 */
 
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <ctype.h>
#include <sys/socket.h>
 
#include "tcp_client.h"
 
/*
 * TCP I/O private data (initialized by netLineInit ())
 */
struct NetLine {
	unsigned defLineLength;
	unsigned cbBuff;
	char *pBuff;
	TSocket sockfd;
};
 
static inline int readChar (int sockfd, char *);
static inline int writeBlock (int sockfd, const char *, size_t);
 
/*
 * Connect to remote server
 * Set sockfd in *pSock
 * Return 0 if no error occur
 */
int netConnect (const char *serverName, unsigned portNumber, TSocket *pSock) {
	// Server address
	struct sockaddr_in sa;
	bzero (&sa, sizeof (sa));
	sa.sin_family = PF_INET;
	sa.sin_port = htons (portNumber);
 
	// Deteremine type of addr (IP/URL)
	if (isdigit(*serverName)) {
		// Direct IP adress
		if (0>= inet_pton (PF_INET, serverName, &sa.sin_addr)) {
			return 1;
		}
	} else {
		// NS-lookup
		struct hostent *pHost;
		if (NULL== (pHost= gethostbyname (serverName))) {
			return 1;
		}
		memcpy (&sa.sin_addr, pHost->h_addr_list[0], pHost->h_length);	
	}
 
	// Create socket
	if (0> (*pSock = socket (PF_INET, SOCK_STREAM, 0))) {
		return 1;
	}
 
	// Connect to server
	if (0!= connect (*pSock, (const struct sockaddr*) &sa, sizeof (sa))) {
		close (*pSock);
		return 1;
	}
 
	return 0;
}
 
/*
 * Close opened socket
 */
void netClose (TSocket socket) {
	close (socket);
}
 
/*
 * Initialize TCP I/O
 */
PNetLine netLineInit (TSocket socket, unsigned defLineLength) {
	PNetLine pNL = malloc (sizeof (TNetLine));
	if (NULL== pNL)
		return NULL;
 
	pNL->sockfd = socket;
	pNL->defLineLength = defLineLength;
	pNL->cbBuff= defLineLength;
	pNL->pBuff = malloc (defLineLength *sizeof(char));
 
	return pNL;
}
 
/*
 * Destroy TCP I/O
 */
void netLineDestroy (PNetLine pNL) {
	free (pNL->pBuff);
	free (pNL);
}
 
/*
 * Read one line from other side
 */
int netLineGet (PNetLine pNL, const char **szText) {
	// Initial allocation
	if (pNL->cbBuff != pNL->defLineLength) {
		pNL->cbBuff= pNL->defLineLength;
		free (pNL->pBuff);
		pNL->pBuff = malloc (pNL->cbBuff *sizeof(char));
	}
 
	// Read one line
	unsigned cbWritten=0;
	while ( 0<readChar (pNL->sockfd, pNL->pBuff + cbWritten) && pNL->pBuff[cbWritten] != '\r')
		if (++cbWritten >= pNL->cbBuff) {
			pNL->cbBuff <<= 1;
			if (NULL== (pNL->pBuff= realloc (pNL->pBuff, pNL->cbBuff) ))
				return -1;
		}
 
	char tmp;
	if (0>= readChar (pNL->sockfd, &tmp) || '\n'!= tmp)
		// Bad CR-LF sequnce
		return -1;
 
	if (pNL->pBuff [cbWritten] != '\r')
		// Error during reading
		return -1;
 
	// End with zero end return string
	pNL->pBuff [cbWritten] = '\0';
	*szText = pNL->pBuff;
 
	// All ok
	return 0;
}
 
/*
 * Send plain text to other side
 */
int netPut (PNetLine pNL, const char *szText) {
	if (0> writeBlock (pNL->sockfd, szText, strlen (szText)))
		return -1;
 
	return 0;
}
 
/*
 * Read one char from socket
 */
static inline int readChar (int sockfd, char *pTo) {
	while (0> read (sockfd, pTo, 1))
		if (errno != EINTR)
			return -1;
	return 1;
}
 
/*
 * Write block to socket
 */
static inline int writeBlock (int sockfd, const char *pBuff, size_t size) {
	int cbWritten = 0;
	while (size > 0) {
		if (0>= (cbWritten= write (sockfd, pBuff, size) )) {
			if (cbWritten<0 && errno==EINTR)
				cbWritten = 0;
			else
				return -1;
		}
		size -= cbWritten;
		pBuff += cbWritten;
	}
 
	return cbWritten;
}