Blame | Last modification | View Log | Download | RSS feed
/* $Id: socket.c 7 2024-08-25 20:49:55Z nishi $ */
#include "is_socket.h"
#include "is_util.h"
#include "is_log.h"
#include "../config.h"
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
extern struct is_config config;
struct is_message message;
int sock;
struct sockaddr_in addr;
void is_parse_params(const char* str) {
message.params = malloc(sizeof(*message.params));
message.params[0] = NULL;
int i;
int incr = 0;
bool until_end = false;
char* dup = is_strdup(str);
for(i = 0;; i++) {
if(dup[i] == 0 || (!until_end && dup[i] == ' ')) {
char oldc = dup[i];
dup[i] = 0;
char* param = is_strdup(dup + incr);
char** old_params = message.params;
int j;
for(j = 0; old_params[j] != NULL; j++)
;
message.params = malloc(sizeof(*message.params) * (2 + j));
for(j = 0; old_params[j] != NULL; j++) {
message.params[j] = old_params[j];
}
message.params[j] = param;
message.params[j + 1] = NULL;
free(old_params);
incr = i + 1;
if(oldc == 0) break;
} else if(dup[i] == ':' && !until_end) {
until_end = true;
incr = i + 1;
}
}
free(dup);
}
int is_socket_send_cmd(const char* name, const char* cmd) {
char* str = is_strcat(cmd, "\r\n");
if(name != NULL) {
char* old = str;
char* tmp = is_strcat3(":", name, " ");
str = is_strcat(tmp, old);
free(old);
free(tmp);
}
int st = send(sock, str, strlen(str), 0);
free(str);
return st < 0 ? 1 : 0;
}
int is_socket_read_cmd(void) {
char c[2];
c[1] = 0;
char* str = malloc(1);
str[0] = 0;
bool err = false;
bool end = false;
while(1) {
int s = recv(sock, c, 1, 0);
if(s <= 0) {
err = true;
break;
}
if(c[0] == '\n') {
end = true;
break;
} else if(c[0] != '\r') {
char* tmp = str;
str = is_strcat(tmp, c);
free(tmp);
}
}
if(message.prefix != NULL) free(message.prefix);
if(message.params != NULL) {
int i;
for(i = 0; message.params[i] != NULL; i++) {
free(message.params[i]);
}
free(message.params);
}
if(message.command != NULL) free(message.command);
message.prefix = NULL;
message.params = NULL;
message.command = NULL;
if(str[0] == ':') {
int i;
for(i = 0; str[i] != 0; i++) {
if(str[i] == ' ') {
str[i] = 0;
message.prefix = is_strdup(str + 1);
i++;
int start = i;
for(;; i++) {
if(str[i] == ' ' || str[i] == 0) {
char oldc = str[i];
str[i] = 0;
message.command = is_strdup(str + start);
if(oldc != 0) {
i++;
is_parse_params(str + i);
}
break;
}
}
break;
}
}
} else {
int i;
for(i = 0; str[i] != 0; i++) {
if(str[i] == ' ' || str[i] == 0) {
char oldc = str[i];
str[i] = 0;
message.command = is_strdup(str);
if(oldc != 0) {
i++;
is_parse_params(str + i);
}
break;
}
}
}
free(str);
return err ? 1 : 0;
}
int is_socket_init(void) {
if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
is_log("Socket creation failure");
return 1;
}
signal(SIGPIPE, SIG_IGN);
int yes = 1;
if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes)) < 0) {
is_log("setsockopt failure");
return 1;
}
config.send_cmd = is_socket_send_cmd;
config.read_cmd = is_socket_read_cmd;
message.prefix = NULL;
message.params = NULL;
message.command = NULL;
bzero((char*)&addr, sizeof(addr));
addr.sin_family = PF_INET;
addr.sin_addr.s_addr = inet_addr(IRC_SERVER);
addr.sin_port = htons(IRC_PORT);
if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
is_log("Connection failure");
is_log(strerror(errno));
close(sock);
return 1;
}
return 0;
}
int is_socket_close(void) {
config.send_cmd(NULL, "QUIT :Goodbye");
close(sock);
}