-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.c
122 lines (103 loc) · 2.26 KB
/
client.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <nsocker/client.h>
#include <nsocker/fd.h>
#include <nsocker/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <assert.h>
#include <endian.h>
#include "errno.h"
void ns_client_init(ns_client *ns)
{
ns->sockfd = 0;
ns->flags = 0;
}
bool ns_client_connect(ns_client *ns, const char *path)
{
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0)
return false;
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
assert( strlen(path) < sizeof(sun.sun_path));
strncpy(sun.sun_path, path, sizeof(sun.sun_path));
if (connect(sockfd, (struct sockaddr*)&sun, SUN_LEN(&sun))) {
close(sockfd);
return false;
}
ns->sockfd = sockfd;
return true;
}
int ns_client_socket(ns_client *ns, int domain, int type, int protocol)
{
ns_hdr theader;
ns_tsocket tsocket;
bzero(&theader, sizeof(theader));
bzero(&tsocket, sizeof(tsocket));
ns_hdr_set(&theader, NS_TSOCKET, sizeof(tsocket));
tsocket.domain = htobe32(domain);
tsocket.type = htobe32(type);
tsocket.protocol = htobe32(protocol);
if (!ns_send_blocking(ns->sockfd, &theader, &tsocket, NS_NULL_FD))
return -1;
ns_hdr rheader;
ns_rsocket rsocket;
int fd;
bool eof;
if (!ns_recv_blocking(ns->sockfd, &rheader, &rsocket, sizeof(rsocket), &fd, &eof))
return -1;
if (be32toh(rheader.size) != sizeof(rsocket) + sizeof(rheader)) {
errno = EPROTO;
return -1;
}
if (be32toh(rheader.cmd) != NS_RSOCKET) {
errno = EPROTO;
return -1;
}
if (be32toh(rsocket.error)) {
errno = be32toh(rsocket.error);
return -1;
} else {
return fd;
}
}
void ns_client_free(ns_client *ns)
{
if (ns->sockfd)
close(ns->sockfd);
}
typedef struct {
ns_context ctx;
ns_client client;
} cc;
static void free_cc(ns_context *ctx)
{
ns_client_free(ctx->socket_client);
ns_context_free(ctx);
free(ctx);
}
bool ns_context_push_new(const char *path)
{
cc *cc = malloc(sizeof(*cc));
if (!cc) {
free(cc);
errno = ENOMEM;
return false;
}
ns_context_init(&cc->ctx);
ns_client_init(&cc->client);
cc->ctx.socket_client = &cc->client;
cc->ctx.pop_cb = free_cc;
if(!ns_client_connect(&cc->client, path)) {
free_cc(&cc->ctx);
return false;
}
if (!ns_push(&cc->ctx)) {
errno = ENOMEM;
free_cc(&cc->ctx);
return false;
}
return true;
}