fz/com.c
2021-11-03 08:59:33 +05:30

275 lines
6.7 KiB
C
Raw Blame History

// com.c - v0.3.1
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LINELENGTH 900
#define PORT 6667
int set_socket_timeout(int connectSocket, int milliseconds)
{
struct timeval tv;
tv.tv_sec = milliseconds / 1000;
tv.tv_usec = (milliseconds % 1000) * 1000;
return setsockopt(connectSocket, SOL_SOCKET, SO_RCVTIMEO,
(char *) &tv, sizeof tv);
}
// *************************************************************
// stellt verbindung zum ircd her
// int port = ircd-port
// char *ipnum = ipnummer des ircd in xxx.xxx.xxx.xxx -notation
// return -1 = fehler beim socket-erstellen
// return -2 = fehler beim connecten
// return num>0 = socketfd
//
int connect_irc(int port, char *ipnum)
{
int create_socket = 0;
struct sockaddr_in address;
if ((create_socket = socket(AF_INET, SOCK_STREAM, 0)) > 0)
printf("The Socket was created\n");
else {
fprintf(stderr, "Unable to create socket\n");
return -1;
}
address.sin_family = AF_INET;
assert(port >= 1 && port <= 65535);
address.sin_port = htons(port);
inet_pton(AF_INET, ipnum, &address.sin_addr);
if (connect
(create_socket, (struct sockaddr *) &address,
sizeof(address)) == 0)
printf("The connection was accepted by %s...\n",
inet_ntoa(address.sin_addr));
else {
fprintf(stderr,
"The connection wasn't accepted by %s...\n",
inet_ntoa(address.sin_addr));
return -2;
}
set_socket_timeout(create_socket, 10);
return create_socket;
}
// *************************************************************
// stellt verbindung zum IPv6 ircd her
// int port = ircd-port
// char *ipnum = ipnummer des ircd in
// xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx -notation
// return -1 = fehler beim socket-erstellen
// return -2 = fehler beim connecten
// return num>0 = socketfd
//
int connect_irc6(int port, char *ipnum)
{
return -1; // FIXME
int create_socket = 0;
struct sockaddr_in6 address;
if ((create_socket = socket(AF_INET6, SOCK_STREAM, 0)) > 0)
printf("The Socket was created %s\n", ipnum);
else {
fprintf(stderr, "Unable to create socket\n");
return -1;
}
address.sin6_family = AF_INET6;
assert(port >= 1 && port <= 65535);
address.sin6_port = htons(port);
inet_pton(AF_INET6, ipnum, &address.sin6_addr);
if (connect
(create_socket, (struct sockaddr *) &address,
sizeof(address)) == 0)
printf("The connection was accepted by %s...\n", ipnum);
else {
fprintf(stderr,
"the connection wasn't accepted by %s...\n",
ipnum);
return -2;
}
set_socket_timeout(create_socket, 10);
return create_socket;
}
// **************************************************************
// schliesst den socket / beendet die Verbindung
//
int disconnect_irc(int socketnum)
{
return (close(socketnum));
}
// ***************************************************************
// sendet einen string an den ircd,
// zu lange strings werden nach stelle LINELENGTH-2 abgeschnitten
// und nen CR-LF (also \r\n) angef<65>gt
// int socketnum = socket-handler
// char *msg = zu sendender string (1-LINELENGTH byte)
// return -2 = string leer
// return -1 = fehler in send()
// return num>0 = <20>bertragene bytes
//
int netsend(int socketnum, char *msg)
{
int len = 0, sended = 0;
len = strlen(msg);
assert(len > 0 && len <= LINELENGTH);
//assert(socketnum > 0);
if (len <= 1) {
fprintf(stderr,
"string zu kurz. mindestl<74>nge 2byte (CR-LF)!\n");
return -2;
}
else if (len > LINELENGTH) {
fprintf(stderr,
"string zu lang. maximall<6C>nge %dbyte (inkl. CR-LF)! \n",
LINELENGTH);
msg[LINELENGTH + 1] = '\0';
msg[LINELENGTH] = '\n';
msg[LINELENGTH - 1] = '\r';
len = strlen(msg);
}
else
// BAUSTELLE if ( BOTFORTH_CRLF == TRUE )
sended = send(socketnum, msg, len, 0);
if (sended == -1) {
fprintf(stderr, "Failed to send to server\n>%s<\n", msg);
return -1;
}
fprintf(stderr, "sended to server: >%s<\n", msg);
return (sended);
}
// ************************************************
// empf<70>ngt eine zeile vom ircd und gibt einen zeiger auf den string zur<75>ck.
// jede zeile des ircd SOLLTE mit einem \r\n abgeschlossen sein.
// die zeilenl<6E>nge ist in LINELENGTH definiert. im RFC ist diese mit maximal
// 512byte (inklusive \r\n) angegeben. standard it aber 255byte
// sollte die zeilenl<6E>nge LINELENGTH <20>berschreiten wird socket geschlossen.
// int socketnum = socketfd zum ircd
// return '\0' = zeile zu lang oder CR-LF-fehler leerer string wird zur<75>ckgegeben und disconnect
// return *char = zeiger auf den empfangenen string
//
char *netrecv(int socketnum)
{
static char buffer[LINELENGTH];
char *a;
int i = 0;
// assert(socketnum > 0);
a = malloc(sizeof(char));
buffer[0] = '\0';
while ((recv(socketnum, a, 1, 0) > 0) && (*a != '\n')) {
if (i >= LINELENGTH - 1) {
fprintf(stderr, "\nERROR: zu lange zeile vom server empfangen\ndisconnect!\n\
i=%d,a=%s,b=%s", i, a, buffer);
exit(1);
disconnect_irc(socketnum);
buffer[0] = '\0';
}
if (*a != '\r') {
buffer[i] = *a;
i++;
}
}
if (i >= 1 && (*a == '\n')) {
//recv(socketnum,a,1,0);
//i++;
if (i > LINELENGTH) {
fprintf(stderr, "\nERROR: zu lange zeile vom server empfangen\ndisconnect!\n\
eingestelle maximall<6C>nge einer zeile ist zZ %d\n",
LINELENGTH);
exit(1);
disconnect_irc(socketnum);
buffer[0] = '\0';
}
if (*a == '\n') {
fprintf(stderr, "\nZeilenende gefunden\n");
buffer[i + 2] = '\0';
buffer[i + 1] = '\n';
buffer[i] = '\r';
} else {
fprintf(stderr,
"\nERROR: mit den zeilenenden stimmt was nicht\n");
disconnect_irc(socketnum);
buffer[0] = '\0';
return (buffer);
}
}
// todo: was ist mit a? speicherleck?
free(a);
return (buffer);
}
int resolve_ircd(char *host, int port)
{
struct hostent *he;
// struct in6_addr addr6;
struct in_addr addr;
// char ipv6[INET6_ADDRSTRLEN];
printf("Resolving host: %s\n", host);
/*
// Resolve IPv6
he = gethostbyname2(host, AF_INET6);
//he=NULL;
if (he == NULL)
printf("Host %s got no IPv6 address\n", host);
else {
inet_ntop(AF_INET6, (void *) he->h_addr_list[0], ipv6,
INET6_ADDRSTRLEN);
printf
("Host %s got IPv6 address %s\nConnecting (IPv6)...\n",
host, ipv6);
return (connect_irc6(port, ipv6));
}
*/
// Resolve IPv4
he = gethostbyname(host);
if (he == NULL)
printf("Host %s got no IPv4 address.\n", host);
else {
memcpy(&addr, he->h_addr_list[0], sizeof(struct in_addr));
printf("Host %s got IPv4 address %s\nConnecting (IPv4)...",
host, inet_ntoa(addr));
return (connect_irc(port, inet_ntoa(addr)));
}
return 0;
}