diff --git a/Makefile b/Makefile index 62667e9..0450b1e 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,11 @@ -LIBS=$(shell pkg-config --libs gnutls) -CFLAGS=-g3 -Wall $(shell pkg-config --cflags gnutls) +LIBS=$(shell pkg-config --libs gnutls nettle hogweed) -lgmp -O3 +CFLAGS=-O3 -Wall $(shell pkg-config --cflags gnutls) PREFIX=/usr -all: socialtest libsocial.so libsocial.pc +all: libsocial.js -libsocial.so: CFLAGS+=-fPIC -libsocial.so: social.o peer.o update.o udpstream.o - $(CC) -shared $^ $(LIBS) -o $@ +libsocial.js: social.o peer.o update.o udpstream.o + $(CC) -shared $^ $(LIBS) -s EXPORTED_FUNCTIONS="['_social_init','_peer_handlesocket','_peer_new_unique']" -s RESERVED_FUNCTION_POINTERS=1 -o $@ libsocial.pc: echo 'prefix=$(PREFIX)' > libsocial.pc diff --git a/peer.c b/peer.c index 7d02247..e918944 100644 --- a/peer.c +++ b/peer.c @@ -211,19 +211,14 @@ void peer_init(const char* keypath) if(!privkey) { gnutls_x509_privkey_init(&privkey); - struct stat st; +// struct stat st; char loadfailed=1; - if(!stat(keypath, &st)) { gnutls_datum_t keydata; - keydata.size=st.st_size; - keydata.data=malloc(st.st_size); - int f=open(keypath, O_RDONLY); - read(f, keydata.data, st.st_size); - close(f); + keydata.size=strlen(keypath); + keydata.data=keypath; // TODO: Allow encrypted keys, using _import2() if(!gnutls_x509_privkey_import2(privkey, &keydata, GNUTLS_X509_FMT_PEM, 0, GNUTLS_PKCS_PLAIN)){loadfailed=0;} - free(keydata.data); } if(loadfailed) { @@ -232,12 +227,13 @@ void peer_init(const char* keypath) gnutls_x509_privkey_generate(privkey, GNUTLS_PK_RSA, 3072, 0); // printf("Done\n"); // TODO: Allow exporting encrypted key, using _export2_pkcs8() I think - gnutls_datum_t keydata; - gnutls_x509_privkey_export2(privkey, GNUTLS_X509_FMT_PEM, &keydata); - int f=open(keypath, O_WRONLY|O_TRUNC|O_CREAT, 0600); - write(f, keydata.data, keydata.size); - close(f); - gnutls_free(keydata.data); +// TODO: Return this to the user, somewhere (or to the server, if password-protecting it is secure enough for that and the user registers a username to tie it to) +// gnutls_datum_t keydata; +// gnutls_x509_privkey_export2(privkey, GNUTLS_X509_FMT_PEM, &keydata); +// int f=open(keypath, O_WRONLY|O_TRUNC|O_CREAT, 0600); +// write(f, keydata.data, keydata.size); +// close(f); +// gnutls_free(keydata.data); } size_t size=ID_SIZE; gnutls_x509_privkey_get_key_id(privkey, GNUTLS_KEYID_USE_SHA256, peer_id, &size); @@ -390,7 +386,7 @@ void peer_bootstrap(int sock, const char* peerlist) #define readordie(x,y,z) {ssize_t r=gnutls_record_recv(x->tls,y,z); if(z && r<1){peer_disconnect(x, 0); continue;}} void peer_handlesocket(int sock) // Incoming data { - udpstream_readsocket(sock); // If it locks up here we're probably missing a bootstrap node +// udpstream_readsocket(sock); // If it locks up here we're probably missing a bootstrap node struct peer* peer; while((peer=findpending())) { diff --git a/social.c b/social.c index 6c05f24..171e7a8 100644 --- a/social.c +++ b/social.c @@ -66,6 +66,7 @@ static void user_save(struct user* user) static void user_load(struct user* user) { +/* // Load user data (only pubkey atm), but spare pubkey if it's already set if(!user->pubkey) { @@ -96,6 +97,7 @@ static void user_load(struct user* user) read(f, buf, size); social_update_parse(user, buf, size); } +*/ } static struct user* user_new(const unsigned char id[ID_SIZE]) diff --git a/udpstream.c b/udpstream.c index ba57da5..3b232f9 100644 --- a/udpstream.c +++ b/udpstream.c @@ -61,6 +61,7 @@ struct udpstream unsigned int buflen; unsigned char state; time_t timestamp; + uint16_t wsseq; // TODO: add void pointer to keep relevant application data? plus a function to free it if the connection is closed or abandoned as stale }; @@ -83,6 +84,7 @@ static struct udpstream* stream_new(int sock, struct sockaddr* addr, socklen_t a stream->buflen=0; stream->state=0; // Start new streams as invalid, need to init stream->timestamp=time(0); + stream->wsseq=0; ++streamcount; streams=realloc(streams, sizeof(void*)*streamcount); streams[streamcount-1]=stream; @@ -102,6 +104,7 @@ struct udpstream* udpstream_find(struct sockaddr* addr, socklen_t addrlen) return 0; } +/* static ssize_t stream_send(struct udpstream* stream, uint8_t type, uint16_t seq, uint32_t size, const void* buf) { // TODO: Include a checksum in the header? @@ -137,6 +140,7 @@ static void udpstream_requestresend(struct udpstream* stream, uint16_t seq) if(!missedcount){return;} stream_send(stream, TYPE_RESEND, 0, missedcount*sizeof(uint16_t), missed); } +*/ static void stream_free(struct udpstream* stream) { @@ -167,10 +171,12 @@ struct udpstream* udpstream_new(int sock, struct sockaddr* addr, socklen_t addrl { struct udpstream* stream=stream_new(sock, addr, addrlen); stream->state=STATE_INIT; // If we're creating the stream we're the ones initializing it - stream_send(stream, TYPE_INIT, 0, 0, 0); +// TODO: Notify webpeer so it'll initiate the connection? I guess the TLS handshake takes care of that +// stream_send(stream, TYPE_INIT, 0, 0, 0); return stream; } +/* void udpstream_readsocket(int sock) { time_t now=time(0); @@ -288,14 +294,16 @@ fprintf(stderr, "TODO: resend packets\n"); } } } +*/ struct udpstream* udpstream_poll(void) { - time_t now=time(0); +// time_t now=time(0); unsigned int i; for(i=0; istate&STATE_CLOSED){return streams[i];} // Check for the next packet in the order unsigned int i2; @@ -303,6 +311,7 @@ struct udpstream* udpstream_poll(void) { if(streams[i]->recvpackets[i2].seq==streams[i]->inseq){return streams[i];} } +/* // Send ping if it's been 20 seconds without any data, unless we already sent one if(streams[i]->timestamp+20state&STATE_PING)) { @@ -320,6 +329,7 @@ struct udpstream* udpstream_poll(void) return streams[i]; } } +*/ } return 0; } @@ -355,8 +365,10 @@ ssize_t udpstream_read(struct udpstream* stream, void* buf, size_t size) return -1; } +void(*websockproxy_write)(struct sockaddr*, socklen_t, const void*, size_t); ssize_t udpstream_write(struct udpstream* stream, const void* buf, size_t size) { +/* if(stream->state&(STATE_CLOSED|STATE_CLOSING)){return 0;} // EOF, TODO: -1 and EBADFD for STATE_CLOSING? // TODO: abort and return negative if sentpacketcount is too high? EWOULDBLOCK? ++stream->sentpacketcount; @@ -367,6 +379,8 @@ ssize_t udpstream_write(struct udpstream* stream, const void* buf, size_t size) memcpy(stream->sentpackets[stream->sentpacketcount-1].buf, buf, size); stream_send(stream, TYPE_PAYLOAD, stream->outseq, size, buf); ++stream->outseq; +*/ + websockproxy_write(&stream->addr, stream->addrlen, buf, size); return size; } @@ -380,11 +394,31 @@ int udpstream_getsocket(struct udpstream* stream){return stream->sock;} void udpstream_close(struct udpstream* stream) { - if(stream->state&STATE_CLOSED) // Closed by peer, just free it - { +// if(stream->state&STATE_CLOSED) // Closed by peer, just free it +// { stream_free(stream); +/* }else{ stream->state|=STATE_CLOSING; stream_send(stream, TYPE_CLOSE, 0, 0, 0); } +*/ +} + +void websockproxy_setwrite(void(*writefunc)(struct sockaddr*, socklen_t, const void*, size_t)) +{ + websockproxy_write=writefunc; +} +void websockproxy_read(struct sockaddr* addr, socklen_t addrlen, const void* buf, size_t payloadsize) +{ + // Find the stream + struct udpstream* stream=udpstream_find(addr, addrlen); + if(!stream){stream=stream_new(-1, addr, addrlen);} + // Add to list of parsed packets + ++stream->recvpacketcount; + stream->recvpackets=realloc(stream->recvpackets, sizeof(struct packet)*stream->recvpacketcount); + stream->recvpackets[stream->recvpacketcount-1].seq=(stream->wsseq++); + stream->recvpackets[stream->recvpacketcount-1].buf=malloc(payloadsize); + stream->recvpackets[stream->recvpacketcount-1].buflen=payloadsize; + memcpy(stream->recvpackets[stream->recvpacketcount-1].buf, buf, payloadsize); } diff --git a/update.c b/update.c index aa69d92..8ad78dc 100644 --- a/update.c +++ b/update.c @@ -26,6 +26,7 @@ #include "social.h" #include "update.h" +/* static void mkdirp(char* path) { char* next=path; @@ -38,6 +39,7 @@ static void mkdirp(char* path) slash[0]='/'; } } +*/ void social_update_write(struct buffer* buf, struct update* update) { @@ -109,6 +111,7 @@ void social_update_sign(struct update* update) void social_update_save(struct user* user, struct update* update) { +/* char path[strlen(social_prefix)+strlen("/updates/0")+ID_SIZE*2]; sprintf(path, "%s/updates/"PEERFMT, social_prefix, PEERARG(user->id)); mkdirp(path); @@ -124,6 +127,7 @@ void social_update_save(struct user* user, struct update* update) buffer_deinit(buf); close(f); // TODO: Is it bad to close and reopen a file in rapid succession? if it is maybe we should implement some kind of cache for cases where we're saving many updates fast, like receiving someone else's updates for the first time +*/ } struct update* social_update_getfield(struct user* user, const char* name)