-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvoipms.c
251 lines (208 loc) · 7.44 KB
/
voipms.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <weechat/weechat-plugin.h>
#include "voipms.h"
#include "buffers.h"
#include "sip_client.h"
#include "history.h"
WEECHAT_PLUGIN_NAME("voipms")
WEECHAT_PLUGIN_DESCRIPTION("send and receive sms from your voip.ms account")
WEECHAT_PLUGIN_AUTHOR("Rex Roni")
WEECHAT_PLUGIN_VERSION("0.2")
WEECHAT_PLUGIN_LICENSE("UNLICENSE")
// optional
WEECHAT_PLUGIN_PRIORITY(1000)
// global variables
struct t_weechat_plugin *weechat_plugin;
struct t_gui_buffer* voip_buffer;
const char* wc_dir;
static int do_sms(const void* ptr, void* data, struct t_gui_buffer* cmd_buffer,
int argc, char** argv, char** argv_eol){
(void)ptr;
(void)data;
if(argc < 3){
weechat_printf(cmd_buffer, "/sms needs a number and a message");
return WEECHAT_RC_ERROR;
}
// build a SIP uri from the phone number that was given
char sip_uri[256];
size_t max_num_len = sizeof(sip_uri) - strlen(REALM) - 5; // sip: @ and \0
size_t len = 0;
len += sprintf(sip_uri, "sip:");
// copy the sip_uri, but ignoring any non-digit characters
for(char *c = argv[1]; *c != '\0' && len < max_num_len; c++){
if(isdigit(*c)) sip_uri[len++] = *c;
}
len += sprintf(sip_uri + len, "@" REALM);
// ignore what buffer this was called from
struct t_gui_buffer* buffer = sip_buffers_get(sip_uri, len);
if(!buffer) return WEECHAT_RC_ERROR;
return voip_plugin_send_sms(buffer, sip_uri, argv_eol[2]);
}
int voip_plugin_send_sms(struct t_gui_buffer* buffer, const char* sip_uri,
const char* msg){
// echo the input data for the user
weechat_printf_date_tags (buffer, 0, "self_msg", "me:\t%s", msg);
// get the buffer name
const char *name = weechat_buffer_get_string(buffer, "name");
// add the message to the history buffer
hist_add_msg(wc_dir, sip_uri, name, msg, strlen(msg), true);
// send via sip
sip_client_send_sms(sip_uri, msg);
// TODO: error handling
return WEECHAT_RC_OK;
}
int voip_buffer_close_cb(const void* ptr, void* data,
struct t_gui_buffer* buffer){
// don't try to print to voip_buffer any more
voip_buffer = NULL;
return WEECHAT_RC_OK;
}
int voip_plugin_handle_sms(const char* from, size_t flen,
const char* body, size_t blen){
// print to the appropriate weechat buffer
struct t_gui_buffer* buffer = sip_buffers_get(from, flen);
if(!buffer) return WEECHAT_RC_ERROR;
weechat_printf_date_tags(buffer, 0, "notify_highlight", "%s%.*s",
weechat_color("green"), (int)blen, body);
// get the buffer name
const char *name = weechat_buffer_get_string(buffer, "name");
// get the sip_uri info from the "from" field
char* sip_uri = dup_only_sip_uri(from, flen);
if(sip_uri){
// add the message to the history buffer
hist_add_msg(wc_dir, sip_uri, name, body, blen, false);
free(sip_uri);
}
return WEECHAT_RC_OK;
}
// we are mime-stoopid for now
int voip_plugin_handle_mms(const char* from, size_t flen,
const char* mime, size_t mlen,
const char* body, size_t blen){
// get the appropriate weechat buffer
struct t_gui_buffer* buffer = sip_buffers_get(from, flen);
if(!buffer) return WEECHAT_RC_ERROR;
// save to a unique filename based on the time
char d[128];
time_t epoch = time(NULL);
struct tm* tnow = localtime(&epoch);
strftime(d, sizeof(d), "%Y_%H:%M:%S", tnow);
char path[256];
sprintf(path, "%s.mms", d);
weechat_printf_date_tags(buffer, 0, "notify_highlight",
"%sGot message of type %.*s, saving to %s",
weechat_color("green"), (int)mlen, mime, path);
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if(fd >= 0){
write(fd, body, blen);
close(fd);
}
return WEECHAT_RC_OK;
}
void voip_plugin_restore_history(void){
hist_buf_t *hist = NULL;
hist_msg_t *msg = NULL;
// get all history buffers
int ret = list_hist_bufs(wc_dir, &hist);
if(ret) goto fail;
// recreate all the buffers
hist_buf_t *p, *next = hist;
while( (p = next) ){
// open the new buffer
struct t_gui_buffer* buffer;
buffer = sip_buffers_get(p->sip_uri, strlen(p->sip_uri));
weechat_printf_date_tags (buffer, 0, NULL, "%s", p->sip_uri);
// set the name of the buffer
if(p->name) weechat_buffer_set(buffer, "name", p->name);
// get all messages in this buffer
hist_msg_t *msg;
ret = get_hist_msg(wc_dir, p->filename, &msg);
if(ret) goto fail;
hist_msg_t *mp, *mnext = msg;
while( (mp = mnext) ){
// add message to the weechat buffer
if(mp->me){
weechat_printf_date_tags(buffer, mp->time, "self_msg",
"me:\t%s", mp->msg);
}else{
weechat_printf_date_tags(buffer, mp->time, "", "%s%s",
weechat_color("green"), mp->msg);
}
mnext = mp->next;
}
// done with this message history
free_hist_msg(msg);
msg = NULL;
next = p->next;
}
fail:
free_hist_msg(msg);
free_hist_buf(hist);
return;
}
void voip_plugin_init(void){
wc_dir = weechat_info_get("weechat_dir", NULL);
voip_buffer = NULL;
sip_buffers_init();
}
void voip_plugin_cleanup(void){
sip_teardown();
sip_buffers_free();
}
int weechat_plugin_init (struct t_weechat_plugin *plugin,
int argc, char *argv[]){
weechat_plugin = plugin;
voip_plugin_init();
// create a "/sms" command
weechat_hook_command("sms",
"send an sms message",
"number message...",
"number: a 10-digit phone number\n"
"message: the message to send",
NULL,
do_sms, NULL, NULL);
// open the VOIP buffer
voip_buffer = weechat_buffer_new("voipms",
NULL, NULL, NULL,
voip_buffer_close_cb, NULL, NULL);
if(!voip_buffer){
voip_plugin_cleanup();
return WEECHAT_RC_ERROR;
}
// allocate sip_buffers
if(sip_buffers_allocate()){
voip_plugin_cleanup();
return WEECHAT_RC_ERROR;
}
// restore the history
voip_plugin_restore_history();
// launch the pjsip client
if(sip_setup()){
voip_plugin_cleanup();
return WEECHAT_RC_ERROR;
}
return WEECHAT_RC_OK;
}
int weechat_plugin_end (struct t_weechat_plugin *plugin){
voip_plugin_cleanup();
return WEECHAT_RC_OK;
}
int sip_buffer_input_cb(const void* ptr, void* data,
struct t_gui_buffer* buffer, const char* input_data){
(void)data;
// dereference the sip_uri associated with this buffer
const char* sip_uri = (const char*)ptr;
return voip_plugin_send_sms(buffer, sip_uri, input_data);
}
int sip_buffer_close_cb(const void* ptr, void* data,
struct t_gui_buffer* buffer){
(void)data;
// dereference the sip_uri associated with this buffer
const char* sip_uri = (const char*)ptr;
// delete this buffer from our list
sip_buffers_delete(sip_uri);
return WEECHAT_RC_OK;
}