diff --git a/rtmp.c b/rtmp.c new file mode 100644 index 0000000..8a374bd --- /dev/null +++ b/rtmp.c @@ -0,0 +1,316 @@ +/* +** server.c -- a stream socket server demo +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MYPORT 2036 // the port users will be connecting to + +#define BACKLOG 10 // how many pending connections queue will hold + +typedef struct { + char unknown[3]; + char amfSize[3]; + char amfType[1]; + char srcDest[4]; + } amfHeader; + +typedef struct { + char unknown[3]; + int amfSize; + int amfType; + char srcDest[4]; + int bodySize; + int bodyCount; + char *body; + } amfHeader_real; + +amfHeader_real *AMFS = 0x0; + + +int main(void) { + int sockfd, new_fd; // listen on sock_fd, new connection on new_fd + struct sockaddr_in my_addr; // my address information + struct sockaddr_in their_addr; // connector's address information + socklen_t sin_size; + struct sigaction sa; + int yes=1; + + AMFS = (amfHeader_real *)malloc(sizeof(amfHeader_real) * 128); + + if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + perror("socket"); + exit(1); + } + + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { + perror("setsockopt"); + exit(1); + } + + my_addr.sin_family = AF_INET; // host byte order + my_addr.sin_port = htons(MYPORT); // short, network byte order + my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP + memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + + if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { + perror("bind"); + exit(1); + } + + if (listen(sockfd, BACKLOG) == -1) { + perror("listen"); + exit(1); + } +/* + sa.sa_handler = sigchld_handler; // reap all dead processes + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + if (sigaction(SIGCHLD, &sa, NULL) == -1) { + perror("sigaction"); + exit(1); + } +*/ + + while(1) { // main accept() loop + sin_size = sizeof(struct sockaddr_in); + if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { + perror("accept"); + continue; + } + printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr)); +/* + if (!fork()) { // this is the child process + close(sockfd); // child doesn't need the listener +*/ + + if (doHandshake(new_fd) != 0) { + close(new_fd); + exit(0); + } +/* + if (doAccept(new_fd) != 0) { + close(new_fd); + exit(0); + } +*/ + + while (1) { + //bzero(&data,4096); + //recv(new_fd,&data,1,MSG_WAITALL); + /* + if (getAMF(new_fd,data[0]) != 0x0) { + */ + if (getAMF(new_fd) != 0x0) { + printf("Error"); + close(new_fd); + exit(0); + } + } +/* + } +*/ + close(new_fd); // parent doesn't need this + } + + return 0; + } + +int getAMF(int fd) { + int AMF; + int recLen = 0x0; + int amfID = 0x0; + int headerSize = 0x0; + int packetSize = 0x0; + int i = 0x0; + char data[12]; + amfHeader *amfHdr = (amfHeader *)&data; + + recLen = recv(fd,&AMF,1,0); + if (recLen != 1) + return(-1); + + headerSize = (AMF & 0xC0) >> 6; + amfID = (AMF & 0x3F); + + switch(headerSize) { + case 0: + recLen = recv(fd,&data,11,0); + printf("12 Byte Header\n"); + packetSize = (amfHdr->amfSize[0] * 256 * 256) + (amfHdr->amfSize[1] * 256) + amfHdr->amfSize[2]; + printf("PacketSize: [%i]\n",packetSize); + AMFS[amfID].bodySize = packetSize; + AMFS[amfID].bodyCount = 0; + AMFS[amfID].body = (char *)malloc(packetSize); + AMFS[amfID].amfType = amfHdr->amfType[0]; + if (packetSize > 128) { + recv(fd,AMFS[amfID].body + AMFS[amfID].bodyCount,128,0); + AMFS[amfID].bodyCount = 128; + } + break; + case 3: + printf("4 Byte Header\n"); + if ((AMFS[amfID].bodySize - AMFS[amfID].bodyCount) > 128) { + recv(fd,AMFS[amfID].body + (AMFS[amfID].bodyCount - 1),128,0); + AMFS[amfID].bodyCount += 128; + } + else { + printf("Bal: (%i)\n",(AMFS[amfID].bodySize - AMFS[amfID].bodyCount)); + recLen = recv(fd,AMFS[amfID].body + (AMFS[amfID].bodyCount - 1),(AMFS[amfID].bodySize - AMFS[amfID].bodyCount)-1,0); + printf("Received: [%i]\n",recLen); + AMFS[amfID].bodyCount += (AMFS[amfID].bodySize - AMFS[amfID].bodyCount)-1; + } + break; + default: + printf("Unhandled Header Size: [%i]\n",headerSize); + return(-1); + break; + } + if (AMFS[amfID].bodySize == AMFS[amfID].bodyCount) + doProcessPacket(fd,amfID); + return(0x0); + } + +int doProcessPacket(int fd,int amfID) { + printf("WOOP"); + return(0x0); + } + +int getAMF_old(int fd,int amf) { + int recLen = 0x0; + int amfID = 0x0; + int headerSize = 0x0; + int packetSize = 0x0; + char data[12]; + amfHeader *amfHdr = (amfHeader *)&data; + + + headerSize = (amf & 0xC0) >> 6; + amfID = amf & 0x3F; + + printf("AMF ID: [0x%X]\n",amfID); + + switch(headerSize) { + case 0: + printf("12 Byte Header\n"); + recLen = recv(fd,&data,11,0); + printf("Size: [0x%X:0x%X:0x%X]\n",amfHdr->amfSize[0] & 0xFF,amfHdr->amfSize[1] & 0xFF,amfHdr->amfSize[2] & 0xFF); + packetSize = (amfHdr->amfSize[0] * 256 * 256) + (amfHdr->amfSize[1] * 256) + amfHdr->amfSize[2]; + printf("PacketSize: [%i]\n",packetSize); +/* + recLen = recv(fd,&packet,packetSize,0); + if (recLen != packetSize) { + printf("Error Reading Packet\n"); + return(-1); + } +*/ + break; + default: + printf("Unhandled Header Size: [%i]\n",headerSize); + return(-1); + break; + } + + switch (amfHdr->amfType[0]) { + case 0x14: + doAmfFunction(fd,amfID,packetSize); + break; + default: + printf("Unhandled amfType: [0x%X]\n",amfHdr->amfType[0]); + return(-1); + break; + } + return(0x0); + } + +int doAmfFunction(int fd,int amfID,int packetSize) { + int recLen = 0x0; + int i = 0x0; + int ch = 0x0; + char *packet = 0x0; + char function[256]; + + printf("Reading Packet"); + packet = (char *)malloc(packetSize); + recLen = recv(fd,packet,packetSize,MSG_WAITALL); + + for (i = 0;i < packet[2];i++) { + function[i] = packet[i + 3]; + } + function[i] = '\0'; + printf("Function: [%s]\n",function); + if (!strcmp(function,"connect")) + doAccept(fd); + + for (i=0;i= 10 && ch <= 128) + printf("[%c]",ch); + else + printf("[0x%X]",ch); + } + printf("\n"); + return(0x0); + } + + +int doHandshake(int fd) { + int recLen = 0x0; + int i = 0x0; + int cmd = 0x0; + char data1[1536]; + char data2[1536]; + + recLen = read(fd,&cmd,1); + if (cmd != 0x03) { + printf("Invalid Handshake\n"); + return(-1); + } + + recLen = recv(fd,&data1,1536,MSG_WAITALL); + + for (i = 0;i < 1536;i++) { + data2[i] = (char)i; + } + if (send(fd,&cmd,1,0) != 1) { + printf("Error Sending Header\n"); + return(-1); + } + if (send(fd,&data2,1536,0) != 1536) { + printf("Error Sending Hand2\n"); + return(-1); + } + if (send(fd,&data1,1536,0) != 1536) { + printf("Error Sending Hand1\n"); + return(-1); + } + recLen = recv(fd,&data1,1536,MSG_WAITALL); + printf("recLen: [%i]\n",recLen); + + return(0x0); + } + +int doAccept(int fd) { + char data[1024]; + char raw1[] = {0x02,0x00,0x00,0x00,0x00,0x00,0x04,0x05,0x00,0x00,0x00,0x00,0x07,0xeb,0x58,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x96,0x14,0x00,0x00,0x00,0x00,0x02,0x00,0x07,0x5f,0x72,0x65,0x73,0x75,0x6c,0x74,0x00,0x3f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x03,0x00,0x04,0x63,0x6f,0x64,0x65,0x02,0x00,0x1d,0x4e,0x65,0x74,0x43,0x6f,0x6e,0x6e,0x65,0x63,0x74,0x69,0x6f,0x6e,0x2e,0x43,0x6f,0x6e,0x6e,0x65,0x63,0x74,0x2e,0x53,0x75,0x63,0x63,0x65,0x73,0x73,0x00,0x05,0x6c,0x65,0x76,0x65,0x6c,0x02,0x00,0x06,0x73,0x74,0x61,0x74,0x75,0x73,0x00,0x07,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x05,0x00,0x0b,0x64,0x65,0x73,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x02,0x00,0x15,0x43,0x6f,0x6e,0x6e,0x65,0x63,0x74,0x69,0x6f,0x6e,0x20,0x73,0x75,0x63,0x63,0x65,0x65,0x64,0x65,0x64,0x2e,0x00,0x0e,0x6f,0x62,0x6a,0x65,0x02,0x00,0x00,0x00,0x00,0x00,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x03,0xd0,0x90,0x02,0xc3,0x63,0x74,0x45,0x6e,0x63,0x6f,0x64,0x69,0x6e,0x67,0x00,0x40,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09}; + int recLen = 0x0; + + // recLen = recv(fd,&data,1024,0); + // printf("reLen: [%i]\n",recLen); + recLen = send(fd,&raw1,sizeof(raw1),0); + printf("raw1: [%i:%i]\n",sizeof(raw1),recLen); + + return(0x0); + } +