Subversion Repositories IRCServ

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7 nishi 1
/* $Id: socket.c 7 2024-08-25 20:49:55Z nishi $ */
2
 
3
#include "is_socket.h"
4
 
5
#include "is_util.h"
6
#include "is_log.h"
7
 
8
#include "../config.h"
9
 
10
#include <unistd.h>
11
#include <string.h>
12
#include <errno.h>
13
#include <stdlib.h>
14
#include <stdbool.h>
15
#include <signal.h>
16
#include <sys/socket.h>
17
#include <netinet/tcp.h>
18
#include <arpa/inet.h>
19
 
20
extern struct is_config config;
21
struct is_message message;
22
 
23
int sock;
24
struct sockaddr_in addr;
25
 
26
void is_parse_params(const char* str) {
27
	message.params = malloc(sizeof(*message.params));
28
	message.params[0] = NULL;
29
	int i;
30
	int incr = 0;
31
	bool until_end = false;
32
	char* dup = is_strdup(str);
33
	for(i = 0;; i++) {
34
		if(dup[i] == 0 || (!until_end && dup[i] == ' ')) {
35
			char oldc = dup[i];
36
			dup[i] = 0;
37
 
38
			char* param = is_strdup(dup + incr);
39
 
40
			char** old_params = message.params;
41
			int j;
42
			for(j = 0; old_params[j] != NULL; j++)
43
				;
44
			message.params = malloc(sizeof(*message.params) * (2 + j));
45
			for(j = 0; old_params[j] != NULL; j++) {
46
				message.params[j] = old_params[j];
47
			}
48
			message.params[j] = param;
49
			message.params[j + 1] = NULL;
50
			free(old_params);
51
 
52
			incr = i + 1;
53
			if(oldc == 0) break;
54
		} else if(dup[i] == ':' && !until_end) {
55
			until_end = true;
56
			incr = i + 1;
57
		}
58
	}
59
	free(dup);
60
}
61
 
62
int is_socket_send_cmd(const char* name, const char* cmd) {
63
	char* str = is_strcat(cmd, "\r\n");
64
	if(name != NULL) {
65
		char* old = str;
66
		char* tmp = is_strcat3(":", name, " ");
67
		str = is_strcat(tmp, old);
68
		free(old);
69
		free(tmp);
70
	}
71
	int st = send(sock, str, strlen(str), 0);
72
	free(str);
73
	return st < 0 ? 1 : 0;
74
}
75
 
76
int is_socket_read_cmd(void) {
77
	char c[2];
78
	c[1] = 0;
79
	char* str = malloc(1);
80
	str[0] = 0;
81
	bool err = false;
82
	bool end = false;
83
	while(1) {
84
		int s = recv(sock, c, 1, 0);
85
		if(s <= 0) {
86
			err = true;
87
			break;
88
		}
89
		if(c[0] == '\n') {
90
			end = true;
91
			break;
92
		} else if(c[0] != '\r') {
93
			char* tmp = str;
94
			str = is_strcat(tmp, c);
95
			free(tmp);
96
		}
97
	}
98
	if(message.prefix != NULL) free(message.prefix);
99
	if(message.params != NULL) {
100
		int i;
101
		for(i = 0; message.params[i] != NULL; i++) {
102
			free(message.params[i]);
103
		}
104
		free(message.params);
105
	}
106
	if(message.command != NULL) free(message.command);
107
	message.prefix = NULL;
108
	message.params = NULL;
109
	message.command = NULL;
110
 
111
	if(str[0] == ':') {
112
		int i;
113
		for(i = 0; str[i] != 0; i++) {
114
			if(str[i] == ' ') {
115
				str[i] = 0;
116
				message.prefix = is_strdup(str + 1);
117
				i++;
118
				int start = i;
119
				for(;; i++) {
120
					if(str[i] == ' ' || str[i] == 0) {
121
						char oldc = str[i];
122
						str[i] = 0;
123
						message.command = is_strdup(str + start);
124
						if(oldc != 0) {
125
							i++;
126
							is_parse_params(str + i);
127
						}
128
						break;
129
					}
130
				}
131
				break;
132
			}
133
		}
134
	} else {
135
		int i;
136
		for(i = 0; str[i] != 0; i++) {
137
			if(str[i] == ' ' || str[i] == 0) {
138
				char oldc = str[i];
139
				str[i] = 0;
140
				message.command = is_strdup(str);
141
				if(oldc != 0) {
142
					i++;
143
					is_parse_params(str + i);
144
				}
145
				break;
146
			}
147
		}
148
	}
149
 
150
	free(str);
151
	return err ? 1 : 0;
152
}
153
 
154
int is_socket_init(void) {
155
	if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
156
		is_log("Socket creation failure");
157
		return 1;
158
	}
159
 
160
	signal(SIGPIPE, SIG_IGN);
161
 
162
	int yes = 1;
163
 
164
	if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes)) < 0) {
165
		is_log("setsockopt failure");
166
		return 1;
167
	}
168
 
169
	config.send_cmd = is_socket_send_cmd;
170
	config.read_cmd = is_socket_read_cmd;
171
 
172
	message.prefix = NULL;
173
	message.params = NULL;
174
	message.command = NULL;
175
 
176
	bzero((char*)&addr, sizeof(addr));
177
	addr.sin_family = PF_INET;
178
	addr.sin_addr.s_addr = inet_addr(IRC_SERVER);
179
	addr.sin_port = htons(IRC_PORT);
180
 
181
	if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
182
		is_log("Connection failure");
183
		is_log(strerror(errno));
184
		close(sock);
185
		return 1;
186
	}
187
	return 0;
188
}
189
 
190
int is_socket_close(void) {
191
	config.send_cmd(NULL, "QUIT :Goodbye");
192
	close(sock);
193
}