275 lines
6.7 KiB
C
275 lines
6.7 KiB
C
// 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;
|
||
}
|