diff --git a/util/ddv_socket.cpp b/util/ddv_socket.cpp new file mode 100644 index 00000000..cedcc76c --- /dev/null +++ b/util/ddv_socket.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool socketError = false; +bool socketBlocking = false; + +int DDV_OpenUnix(const char adres[], bool nonblock = false){ + int s = socket(AF_UNIX, SOCK_STREAM, 0); + sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, adres); + int r = connect(s, (sockaddr*)&addr, sizeof(addr)); + if (r == 0){ + if (nonblock){ + int flags = fcntl(s, F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(s, F_SETFL, flags); + } + return s; + }else{ + close(s); + return 0; + } +} + +int DDV_Listen(int port){ + int s = socket(AF_INET, SOCK_STREAM, 0); + + int on = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port);//port 8888 + inet_pton(AF_INET, "0.0.0.0", &addr.sin_addr);//listen on all interfaces + int ret = bind(s, (sockaddr*)&addr, sizeof(addr));//bind to all interfaces, chosen port + if (ret == 0){ + ret = listen(s, 100);//start listening, backlog of 100 allowed + if (ret == 0){ + return s; + }else{ + printf("Listen failed! Error: %s\n", strerror(errno)); + close(s); + return 0; + } + }else{ + printf("Binding failed! Error: %s\n", strerror(errno)); + close(s); + return 0; + } +} + +int DDV_Accept(int sock, bool nonblock = false){ + int r = accept(sock, 0, 0); + if ((r > 0) && nonblock){ + int flags = fcntl(r, F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(r, F_SETFL, flags); + } + return r; +} + +bool DDV_write(void * buffer, int todo, int sock){ + int sofar = 0; + socketBlocking = false; + while (sofar != todo){ + int r = send(sock, (char*)buffer + sofar, todo-sofar, 0); + if (r <= 0){ + switch (errno){ + case EWOULDBLOCK: socketBlocking = true; break; + default: + socketError = true; + printf("Could not write! %s\n", strerror(errno)); + return false; + break; + } + } + sofar += r; + } + return true; +} + +bool DDV_ready(int sock){ + char tmp; + int preflags = fcntl(sock, F_GETFL, 0); + int postflags = preflags | O_NONBLOCK; + fcntl(sock, F_SETFL, postflags); + int r = recv(sock, &tmp, 1, MSG_PEEK); + fcntl(sock, F_SETFL, preflags); + return (r == 1); +} + +bool DDV_read(void * buffer, int todo, int sock){ + int sofar = 0; + socketBlocking = false; + while (sofar != todo){ + int r = recv(sock, (char*)buffer + sofar, todo-sofar, 0); + if (r <= 0){ + switch (errno){ + case EWOULDBLOCK: socketBlocking = true; break; + default: + socketError = true; + printf("Could not read! %s\n", strerror(errno)); + return false; + break; + } + } + sofar += r; + } + return true; +} + + +bool DDV_read(void * buffer, int width, int count, int sock){return DDV_read(buffer, width*count, sock);} +bool DDV_write(void * buffer, int width, int count, int sock){return DDV_write(buffer, width*count, sock);} + + +int DDV_iwrite(void * buffer, int todo, int sock){ + int r = send(sock, buffer, todo, 0); + if (r < 0){ + switch (errno){ + case EWOULDBLOCK: break; + default: + socketError = true; + printf("Could not write! %s\n", strerror(errno)); + return false; + break; + } + } + return r; +} + +int DDV_iread(void * buffer, int todo, int sock){ + int r = recv(sock, buffer, todo, 0); + if (r < 0){ + switch (errno){ + case EWOULDBLOCK: break; + default: + socketError = true; + printf("Could not read! %s\n", strerror(errno)); + return false; + break; + } + } + return r; +} + + diff --git a/util/flv.cpp b/util/flv.cpp index 0e119a52..c04d977a 100644 --- a/util/flv.cpp +++ b/util/flv.cpp @@ -1,4 +1,5 @@ #include //for read() +#include struct FLV_Pack { int len; @@ -8,42 +9,86 @@ struct FLV_Pack { };//FLV_Pack char FLVHeader[13]; +bool All_Hell_Broke_Loose = false; -//reads full length from a file descriptor -void Magic_Read(char * buf, int len, int file){ - int i = 0; - while (i < len) i += read(file, buf, len-i); -} - - -//reads a FLV header and checks for correctness +//checks FLV Header for correctness //returns true if everything is alright, false otherwise -bool FLV_Readheader(){ - fread(FLVHeader,1,13,stdin); - if (FLVHeader[0] != 'F') return false; - if (FLVHeader[1] != 'L') return false; - if (FLVHeader[2] != 'V') return false; - if (FLVHeader[8] != 0x09) return false; - if (FLVHeader[9] != 0) return false; - if (FLVHeader[10] != 0) return false; - if (FLVHeader[11] != 0) return false; - if (FLVHeader[12] != 0) return false; +bool FLV_Checkheader(char * header){ + if (header[0] != 'F') return false; + if (header[1] != 'L') return false; + if (header[2] != 'V') return false; + if (header[8] != 0x09) return false; + if (header[9] != 0) return false; + if (header[10] != 0) return false; + if (header[11] != 0) return false; + if (header[12] != 0) return false; return true; -}//FLV_Readheader +}//FLV_Checkheader + +//returns true if header is an FLV header +bool FLV_Isheader(char * header){ + if (header[0] != 'F') return false; + if (header[1] != 'L') return false; + if (header[2] != 'V') return false; + return true; +}//FLV_Isheader + +bool ReadUntil(char * buffer, unsigned int count, unsigned int & sofar){ + if (sofar >= count){return true;} + int r = 0; + r = fread(buffer + sofar,1,count-sofar,stdin); + if (r < 0){All_Hell_Broke_Loose = true; return false;} + sofar += r; + if (sofar >= count){return true;} + return false; +} //gets a packet, storing in given FLV_Pack pointer. //will assign pointer if null //resizes FLV_Pack data field bigger if data doesn't fit // (does not auto-shrink for speed!) -void FLV_GetPacket(FLV_Pack *& p){ +bool FLV_GetPacket(FLV_Pack *& p){ + int preflags = fcntl(fileno(stdin), F_GETFL, 0); + int postflags = preflags | O_NONBLOCK; + fcntl(fileno(stdin), F_SETFL, postflags); + static bool done = true; + static unsigned int sofar = 0; if (!p){p = (FLV_Pack*)calloc(1, sizeof(FLV_Pack));} if (p->buf < 15){p->data = (char*)realloc(p->data, 15); p->buf = 15;} - fread(p->data,1,11,stdin); - p->len = p->data[3] + 15; - p->len += (p->data[2] << 8); - p->len += (p->data[1] << 16); - if (p->buf < p->len){p->data = (char*)realloc(p->data, p->len);p->buf = p->len;} - fread(p->data+11,1,p->len-11,stdin); - p->isKeyframe = false; - if ((p->data[0] == 0x09) && (((p->data[11] & 0xf0) >> 4) == 1)){p->isKeyframe = true;} + + if (done){ + //read a header + if (ReadUntil(p->data, 11, sofar)){ + //if its a correct FLV header, throw away and read tag header + if (FLV_Isheader(p->data)){ + if (ReadUntil(p->data, 13, sofar)){ + if (FLV_Checkheader(p->data)){ + sofar = 0; + memcpy(FLVHeader, p->data, 13); + }else{All_Hell_Broke_Loose = true;} + } + }else{ + //if a tag header, calculate length and read tag body + p->len = p->data[3] + 15; + p->len += (p->data[2] << 8); + p->len += (p->data[1] << 16); + if (p->buf < p->len){p->data = (char*)realloc(p->data, p->len);p->buf = p->len;} + done = false; + } + } + }else{ + //read tag body + if (ReadUntil(p->data, p->len, sofar)){ + //calculate keyframeness, next time read header again, return true + p->isKeyframe = false; + if ((p->data[0] == 0x09) && (((p->data[11] & 0xf0) >> 4) == 1)){p->isKeyframe = true;} + done = true; + sofar = 0; + fcntl(fileno(stdin), F_SETFL, preflags); + return true; + } + } + fcntl(fileno(stdin), F_SETFL, preflags); + return false; }//FLV_GetPacket + diff --git a/util/flv_sock.cpp b/util/flv_sock.cpp index 8d6c55a4..ac520b43 100644 --- a/util/flv_sock.cpp +++ b/util/flv_sock.cpp @@ -1,30 +1,92 @@ -SWBaseSocket::SWBaseError SWBerr; -char * FLVbuffer; -int FLV_len; -int FLVbs = 0; -void FLV_Readheader(SWUnixSocket & ss){ - static char header[13]; - while (ss.frecv(header, 13, &SWBerr) != 13){ - //wait - } -}//FLV_Readheader +struct FLV_Pack { + int len; + int buf; + bool isKeyframe; + char * data; +};//FLV_Pack -void FLV_Dump(){FLV_len = 0;} +char FLVHeader[13]; +bool All_Hell_Broke_Loose = false; -bool FLV_GetPacket(SWUnixSocket & ss){ - if (FLVbs < 15){FLVbuffer = (char*)realloc(FLVbuffer, 15); FLVbs = 15;} - //if received a whole header, receive a whole packet - //if not, retry header next pass - if (FLV_len == 0){ - if (ss.frecv(FLVbuffer, 11, &SWBerr) == 11){ - FLV_len = FLVbuffer[3] + 15; - FLV_len += (FLVbuffer[2] << 8); - FLV_len += (FLVbuffer[1] << 16); - if (FLVbs < FLV_len){FLVbuffer = (char*)realloc(FLVbuffer, FLV_len);FLVbs = FLV_len;} +//checks FLV Header for correctness +//returns true if everything is alright, false otherwise +bool FLV_Checkheader(char * header){ + if (header[0] != 'F') return false; + if (header[1] != 'L') return false; + if (header[2] != 'V') return false; + if (header[8] != 0x09) return false; + if (header[9] != 0) return false; + if (header[10] != 0) return false; + if (header[11] != 0) return false; + if (header[12] != 0) return false; + return true; +}//FLV_Checkheader + +//returns true if header is an FLV header +bool FLV_Isheader(char * header){ + if (header[0] != 'F') return false; + if (header[1] != 'L') return false; + if (header[2] != 'V') return false; + return true; +}//FLV_Isheader + +bool ReadUntil(char * buffer, unsigned int count, unsigned int & sofar, int sock){ + if (sofar >= count){return true;} + int r = 0; + r = DDV_iread(buffer + sofar,count-sofar,sock); + if (r < 0){All_Hell_Broke_Loose = true; return false;} + sofar += r; + if (sofar >= count){return true;} + return false; +} + +//gets a packet, storing in given FLV_Pack pointer. +//will assign pointer if null +//resizes FLV_Pack data field bigger if data doesn't fit +// (does not auto-shrink for speed!) +bool FLV_GetPacket(FLV_Pack *& p, int sock){ + int preflags = fcntl(sock, F_GETFL, 0); + int postflags = preflags | O_NONBLOCK; + fcntl(sock, F_SETFL, postflags); + static bool done = true; + static unsigned int sofar = 0; + if (!p){p = (FLV_Pack*)calloc(1, sizeof(FLV_Pack));} + if (p->buf < 15){p->data = (char*)realloc(p->data, 15); p->buf = 15;} + + if (done){ + //read a header + if (ReadUntil(p->data, 11, sofar, sock)){ + //if its a correct FLV header, throw away and read tag header + if (FLV_Isheader(p->data)){ + if (ReadUntil(p->data, 13, sofar, sock)){ + if (FLV_Checkheader(p->data)){ + sofar = 0; + memcpy(FLVHeader, p->data, 13); + }else{All_Hell_Broke_Loose = true;} + } + }else{ + //if a tag header, calculate length and read tag body + p->len = p->data[3] + 15; + p->len += (p->data[2] << 8); + p->len += (p->data[1] << 16); + if (p->buf < p->len){p->data = (char*)realloc(p->data, p->len);p->buf = p->len;} + done = false; + } } }else{ - if (ss.frecv(FLVbuffer+11, FLV_len-11, &SWBerr) == FLV_len-11){return true;} + //read tag body + if (ReadUntil(p->data, p->len, sofar, sock)){ + //calculate keyframeness, next time read header again, return true + p->isKeyframe = false; + if ((p->data[0] == 0x09) && (((p->data[11] & 0xf0) >> 4) == 1)){p->isKeyframe = true;} + done = true; + sofar = 0; + fcntl(sock, F_SETFL, preflags); + return true; + } } + fcntl(sock, F_SETFL, preflags); return false; }//FLV_GetPacket +