diff --git a/.gitignore b/.gitignore index 8887b3e..03103b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +*.o +s-talk + .vscode/* !.vscode/settings.json !.vscode/tasks.json @@ -6,4 +9,8 @@ *.code-workspace # Local History for Visual Studio Code -.history/ \ No newline at end of file +.history/ +.vscode/launch.json +.gitignore +.vscode/tasks.json +.vscode/settings.json diff --git a/Makefile b/Makefile index 827f0e7..a3dbc11 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,9 @@ -CFLAGS = -Wall -Werror +CFLAGS = -Wall -Werror -all: - build +all: build build: - gcc $(CFLAGS) launcher.c readInput.c writeOutput.c sendUDP.c receiveUDP.c queueOperations.c -pthread -o s-talk - -run: - build - ./s-talk - - -valgrind: - build - valgrind --leak-check=full ./s-talk - - + gcc $(CFLAGS) launcher.c readInput.c writeOutput.c sendUDP.c receiveUDP.c queueOperations.c list.c threadCanceller.c -o s-talk -lpthread + clean: rm -f s-talk \ No newline at end of file diff --git a/Syeda's socket play/.DS_Store b/Syeda's socket play/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/Syeda's socket play/.DS_Store and /dev/null differ diff --git a/Syeda's socket play/.vscode/launch.json b/Syeda's socket play/.vscode/launch.json deleted file mode 100644 index e3550a9..0000000 --- a/Syeda's socket play/.vscode/launch.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "gcc-7 - Build and debug active file", - "type": "cppdbg", - "request": "launch", - "program": "${fileDirname}/${fileBasenameNoExtension}", - "args": [], - "stopAtEntry": false, - "cwd": "${fileDirname}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ], - "preLaunchTask": "C/C++: gcc-7 build active file", - "miDebuggerPath": "/usr/bin/gdb" - } - ] -} \ No newline at end of file diff --git a/Syeda's socket play/.vscode/settings.json b/Syeda's socket play/.vscode/settings.json deleted file mode 100644 index f094915..0000000 --- a/Syeda's socket play/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "errno.h": "c" - } -} \ No newline at end of file diff --git a/Syeda's socket play/.vscode/tasks.json b/Syeda's socket play/.vscode/tasks.json deleted file mode 100644 index 380b4d6..0000000 --- a/Syeda's socket play/.vscode/tasks.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "tasks": [ - { - "type": "cppbuild", - "label": "C/C++: gcc-7 build active file", - "command": "/usr/bin/gcc-7", - "args": [ - "-g", - "${file}", - "-o", - "${fileDirname}/${fileBasenameNoExtension}" - ], - "options": { - "cwd": "${fileDirname}" - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "detail": "Task generated by Debugger." - } - ], - "version": "2.0.0" -} \ No newline at end of file diff --git a/Syeda's socket play/demoClient.c b/Syeda's socket play/demoClient.c deleted file mode 100644 index d3540c1..0000000 --- a/Syeda's socket play/demoClient.c +++ /dev/null @@ -1,17 +0,0 @@ -// server demo - -#include -#include -#include - -int main(int arg, char* arg[]){ - - - int myServerSock; - struct sockaddr_in server; - char buffer[1024] - - - - return 0; -} \ No newline at end of file diff --git a/Syeda's socket play/demoServer.c b/Syeda's socket play/demoServer.c deleted file mode 100644 index ed37410..0000000 --- a/Syeda's socket play/demoServer.c +++ /dev/null @@ -1,60 +0,0 @@ -// server demo - -#include -#include // textbook -#include //textbook -#include -#include -#include -#include -#include - -int main(int argCount,char* args[]){ - - - #define MESSAGE "Hello World Testing Socket" - - // variables// - int mySock; - struct sockaddr_in server; - struct hostent *hp; - char buffer[1024]; - - //creating socket// - mySock = socket(AF_INET, SOCK_DGRAM, 0); - if(mySock < 0 ){ - perror("socket failed"); - close(mySock); - exit(1); - } - - server.sin_family = AF_INET; - hp = gethostbyname (argv[1]); - if(hp == 0){ - perror("getting host name failed"); - close(mySock); - exit(1); - } - - memcpy(&server.sin_addr, hp->h_addr, hp->h_length); - server.sin_port = htons(5000); - - - if(connect(mySock, (struct sockaaddr *)&server, sizeof(server))<0){ - perror("connection failed"); - close(mySock); - exit(1); - } - - if(send(mySock,MESSAGE, sizeof(MESSAGE),0)<0){ - perror("Sending faild"); - close(mySock); - exit(1); - } - printf("Sent %s\n", MESSAGE); - close(mySock); - - - - return 0; -} \ No newline at end of file diff --git a/Syeda's socket play/demoSocket.c b/Syeda's socket play/demoSocket.c deleted file mode 100644 index 4109f12..0000000 --- a/Syeda's socket play/demoSocket.c +++ /dev/null @@ -1,73 +0,0 @@ -// demo -// following youtube demo "C Programming in Linux Tutorial #034 - Socket Programming" -// ^^ cite it : https://www.youtube.com/watch?v=pFLQkmnmD0o&list=PLypxmOPCOkHXbJhUgjRaV2pD9MJkIArhg&index=34 - -#include -#include // textbook -#include //textbook -#include -#include -#include - -#define PORT 22110 - -int main(int argCount,char* args[]){ - // variables// - - // brian no have// - int mysocket; // s in tutoial // sock in vid - char buffer[1024]; - int myAcceptingSocket; - int rval; - - //brian had// - struct sockaddr_in server; - - //creating socket// - mysocket = socket(AF_INET, SOCK_DGRAM, 0); //AF-> allows communication - - // brian had// - server.sin_family = AF_INET; - server.sin_addr.s_addr = htonl(INADDR_ANY); - server.sin_port = htons(PORT); - memset(&server,0, sizeof(server)); - - //binding socket// - - if(bind(mysocket, (struct sockaddr* )&server, sizeof(server)) ){ - perror("this bind faild"); - exit(1); - } - - - //listening// - - listen(mysocket,5); - - - //accept// - do{ - myAcceptingSocket = accept(mysocket, (struct sockaddr *)0,0); - if(myAcceptingSocket == -1){ - perror("could not accept, failed attempt"); - } - else{ - memset(buffer, 0, sizeof(buffer)); - if(rval == recv(myAcceptingSocket, buffer, sizeof(buffer),0) < 0 ){ - perror("reading the message failed"); - } - else if(rval==0){ - printf("ending connection"); - } - else{ - printf("Message is: %s\n", buffer); - - } - printf("We recieved the message: (rval = %d\n)", rval); - close(myAcceptingSocket); - } - } - while(1); - - return 0; -} \ No newline at end of file diff --git a/Syeda's socket play/socketB1 b/Syeda's socket play/socketB1 deleted file mode 100755 index 54f0967..0000000 Binary files a/Syeda's socket play/socketB1 and /dev/null differ diff --git a/Syeda's socket play/socketBrian b/Syeda's socket play/socketBrian deleted file mode 100755 index dbfb2b6..0000000 Binary files a/Syeda's socket play/socketBrian and /dev/null differ diff --git a/Syeda's socket play/socketBrian.c b/Syeda's socket play/socketBrian.c deleted file mode 100644 index 640e762..0000000 --- a/Syeda's socket play/socketBrian.c +++ /dev/null @@ -1,67 +0,0 @@ -//sockett - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PORT 22110 -#define MAX_LENGTH 1024 -char messageBuffer[MAX_LENGTH]; // buffer to store the message data - -int main(int argCount,char* args[]){ - - printf("Hello!\n"); - printf("to connect do: netcat -u 127.0.0.1 %d\n", PORT); - - - - // setting up socket -- brian had // - struct sockaddr_in server; - memset(&server,0, sizeof(server)); // clear the socket - server.sin_family = AF_INET; - server.sin_addr.s_addr = htonl(INADDR_ANY); // in address any, willing to work on any local port, - //dont care about port sending to - server.sin_port = htons(PORT); // port to connect to - - - // creating socket// - int mysocket = socket(PF_INET, SOCK_DGRAM, 0); - //before was AF instead PF -- domain = AF-> allows communication and binding so it can talk to another port - // type = DGRAM -> connectionless socket,for UDP, no need to maintain open connection - - // binding socket // - int bindval= bind(mysocket, (struct sockaddr *)&server, sizeof(server)); - - - while(1){ - - // recieve data// - struct sockaddr_in messageFrom; // lets us know who we got message from, brian had sinRemote - unsigned int messageLen = sizeof(messageFrom); // the length - int bytesOfMesssage = recvfrom(mysocket, messageBuffer, MAX_LENGTH, 0, (struct sockaddr *)&messageFrom,&messageLen); // main function to recieve - - int interminateNull = (bytesOfMesssage < MAX_LENGTH) ? bytesOfMesssage : MAX_LENGTH -1; - messageBuffer[interminateNull] = 0; - printf("message recived successfully by: %d bytes: \n\n %s\n", bytesOfMesssage,messageBuffer); - if(messageBuffer == NULL){ - printf("repeat--> %s\n", messageBuffer); - } - - - } - - - //close socket// - - close(mysocket); - - -} - diff --git a/assn1 b/assn1 deleted file mode 100755 index df069ca..0000000 Binary files a/assn1 and /dev/null differ diff --git a/assn1.dSYM/Contents/Info.plist b/assn1.dSYM/Contents/Info.plist deleted file mode 100644 index c12d12e..0000000 --- a/assn1.dSYM/Contents/Info.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - com.apple.xcode.dsym.assn1 - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - dSYM - CFBundleSignature - ???? - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/assn1.dSYM/Contents/Resources/DWARF/assn1 b/assn1.dSYM/Contents/Resources/DWARF/assn1 deleted file mode 100644 index 040c350..0000000 Binary files a/assn1.dSYM/Contents/Resources/DWARF/assn1 and /dev/null differ diff --git a/launcher.c b/launcher.c new file mode 100644 index 0000000..158238f --- /dev/null +++ b/launcher.c @@ -0,0 +1,49 @@ +#include +#include +#include + +#include "list.h" +#include "readInput.h" +#include "writeOutput.h" +#include "receiveUDP.h" +#include "sendUDP.h" + +// Launches the s-talk program +int main (int argc, char * argv[]) +{ + // Checks if arguments are correct + if (argc!=4) + { + printf("Please enter valid arguments \n"); + printf("Valid argument strucure is: \n"); + printf("s-talk [my port number] [remote machine name] [remote port number]\n"); + return -1; + } + + // Storing arguments + char* myPort = argv[1]; + char* theirHostname = argv[2]; + char* theirPort = argv[3]; + + // Creates a shared list + List* list = List_create(); + + // Initializes the four modules + // Modules are running in an infinite loop, they will exit when given the exit code "!" + readerInit(list); + senderInit(theirHostname, theirPort, list); + receiverInit(myPort, list); + writerInit(list); + + // Cleans up the threads + readerShutdown(); + senderShutdown(); + receiverShutdown(); + writerShutdown(); + + // Frees the list + // At this point, the list should already be empty + List_free(list, free); + + return 0; +} \ No newline at end of file diff --git a/list.c b/list.c index 8d5c025..f595d28 100644 --- a/list.c +++ b/list.c @@ -217,7 +217,7 @@ void* List_next(List* pList) return NULL; } - if(pList->current==pList->tail || pList->current==NULL && pList->oob==LIST_OOB_END) + if(pList->current==pList->tail || (pList->current==NULL && pList->oob==LIST_OOB_END)) { pList->oob = LIST_OOB_END; pList->current = NULL; @@ -246,7 +246,7 @@ void* List_prev(List* pList) return NULL; } - if(pList->current == pList->head || pList->current==NULL && pList->oob==LIST_OOB_START) + if(pList->current == pList->head || (pList->current==NULL && pList->oob==LIST_OOB_START)) { pList->oob = LIST_OOB_START; pList->current = NULL; @@ -489,7 +489,10 @@ void List_free(List* pList, FREE_FN pItemFreeFn) Node* temp = pList->current; pList->current = pList->current->next; - (*pItemFreeFn)(temp->item); + if(pItemFreeFn!=NULL) + { + (*pItemFreeFn)(temp->item); + } pushNodeMem(temp); } @@ -530,6 +533,10 @@ typedef bool (*COMPARATOR_FN)(void* pItem, void* pComparisonArg); void* List_search(List* pList, COMPARATOR_FN pComparator, void* pComparisonArg) { assert(pList!=NULL); + if(pComparator==NULL) + { + return NULL; + } if(pList->numItems==0) { diff --git a/list.o b/list.o deleted file mode 100644 index 84c9580..0000000 Binary files a/list.o and /dev/null differ diff --git a/main.c b/main.c deleted file mode 100644 index 1e8183b..0000000 --- a/main.c +++ /dev/null @@ -1,811 +0,0 @@ -#include -#include -#include -#include -#include"list.h" - -// Funcion to free statically allocated items -// Empty because deletion of statically allocated items are handled by the compiler -void freeStatic(void* pItem) -{ - return; -} - -// Function to free dynamically allocated items -void freeDynamic (void* pItem) -{ - free(pItem); -} - -// Function to compare integers -bool compareInt (void* pItem, void* pComparisonArg) -{ - return *(int*)pItem==*(int*)pComparisonArg; -} - -// Testing List_Create(), List_Free() and the head max limit to see if memory management works -void testHeadRelated() -{ - printf("\n\nTesting list create and head limit \n"); - int i; - List* heads[12]; - printf("Creating an array of size 12 of pointers to heads \n"); - for (i=0;i<12;i++) - { - heads[i]=List_create(); - } - - printf("Printing the pointers to the heads in the array \n"); - for(i=0;i<12;i++) - { - printf("Value inside heads[%d]: %p \n",i,heads[i]); - } - printf("Expected result : heads[10] and heads[11] are NULL pointers \n"); - - printf("\nTesting List_free \n"); - printf("Deleting all currently allocated heads \n"); - for (i=0;i<12;i++) - { - if(heads[i]!=NULL) - { - List_free(heads[i],&freeStatic); - } - } - printf("Re-creating an array of size 10 of pointers to heads \n"); - for (i=0;i<10;i++) - { - heads[i]=List_create(); - printf("Value inside heads[%d]: %p \n",i,heads[i]); - } - printf("Expected: No null pointers\n"); - printf("Deleting all currently allocated heads \n"); - for (i=0;i<12;i++) - { - if(heads[i]!=NULL) - { - List_free(heads[i],&freeStatic); - } - } -} - -void testListCount() -{ - printf("\n\nTesting List_count function\n"); - printf("Creating empty head\n"); - List* head = List_create(); - printf("List_count(head) = %d (expected = 0)\n",List_count(head)); - printf("Adding a node to head\n"); - int testItem = 0; - List_add(head, &testItem); - printf("List_count(head) = %d (expected = 1)\n",List_count(head)); - printf("Deleting a node\n"); - List_remove(head); - printf("List_count(head) = %d (expected = 0)\n",List_count(head)); - printf("Deleting all currently allocated heads \n"); - List_free(head,&freeStatic); - -} - -// Testing traversal functions; List_first, List_last, List_next, List_prev, List_curr -void testListTraversal() -{ - printf("\n\nTesting traversal functions \n"); - printf("Creating empty head\n"); - List* head = List_create(); - printf("List_first(head) = %p (expected NULL)\n", List_first(head)); - printf("List_last(head) = %p (expected NULL)\n", List_last(head)); - printf("List_next(head) = %p (expected NULL)\n", List_next(head)); - printf("List_prev(head) = %p (expected NULL)\n", List_prev(head)); - printf("List_curr(head) = %p (expected NULL)\n", List_curr(head)); - - printf("\nAdding one node to the head with value integer 0 \n"); - int testItem = 0; - List_add(head, &testItem); - printf("*(int*)List_first(head) = %d (expected 0)\n", *(int*)List_first(head)); - printf("*(int*)List_last(head) = %d (expected 0)\n", *(int*)List_last(head)); - printf("*(int*)List_curr(head) = %d (expected 0)\n", *(int*)List_curr(head)); - - printf("\n Testing next and prev with 1 node, also testing behaviour when beyond start/end\n"); - printf("List_next(head) = %p (expected NULL)\n",List_next(head)); - printf("head->oob = %d (expected 1 (oob end)) \n",head->oob); - printf("List_next(head) = %p (expected NULL)\n",List_next(head)); - printf("head->oob = %d (expected 1 (oob end)) \n",head->oob); - printf("*(int*)List_prev(head) = %d (expected 0)\n", *(int*)List_prev(head)); - printf("List_prev(head) = %p (expected NULL)\n",List_prev(head)); - printf("head->oob = %d (expected 0 (oob start)) \n",head->oob); - printf("List_prev(head) = %p (expected NULL)\n",List_prev(head)); - printf("head->oob = %d (expected 0 (oob start)) \n",head->oob); - printf("*(int*)List_next(head) = %d (expected 0)\n", *(int*)List_next(head)); - - printf("\nAdding another node to the head with value integer 1 (current item count =2)\n"); - int testItem1=1; - List_add(head, &testItem1); - printf("*(int*)List_first(head) = %d (expected 0)\n", *(int*)List_first(head)); - printf("*(int*)List_last(head) = %d (expected 1)\n", *(int*)List_last(head)); - printf("*(int*)List_curr(head) = %d (expected 1)\n", *(int*)List_curr(head)); - - printf("\n Testing next and prev with 2 nodes\n"); - printf("*(int*)List_prev(head) = %d (expected 0)\n", *(int*)List_prev(head)); - printf("*(int*)List_next(head) = %d (expected 1)\n", *(int*)List_next(head)); - - - printf("\nDeleting all currently allocated heads \n"); - List_free(head,&freeStatic); -} - -// Testing the addition functions: List_add, List_insert, List_append, List_prepend -void testListAddition() -{ - printf("\n\nTesting addition functions\n"); - printf("\nTesting adding into empty lists \n"); - List* heads[4]; - for (int i=0;i<4;i++) - { - heads[i] = List_create(); - } - int testItem0=0; - List_add(heads[0], &testItem0); - List_insert(heads[1], &testItem0); - List_append(heads[2], &testItem0); - List_prepend(heads[3], &testItem0); - printf("Current item in heads[0] after adding 0 = %d \n", *(int* ) List_curr(heads[0])); - printf("Current item in heads[1] after inserting 0 = %d \n", *(int* ) List_curr(heads[1])); - printf("Current item in heads[2] after appending 0 = %d \n", *(int* ) List_curr(heads[2])); - printf("Current item in heads[3] after prepending 0 = %d \n", *(int* ) List_curr(heads[3])); - - printf("\nAdding 1 and 2 with each addition method for each element of heads\n"); - int testItem1=1; - List_add(heads[0], &testItem1); //0 1 - List_insert(heads[1], &testItem1); // 1 0 - List_append(heads[2], &testItem1); // 0 1 - List_prepend(heads[3], &testItem1); // 1 0 - - int testItem2=2; - List_add(heads[0], &testItem2); //0 1 2 - List_insert(heads[1], &testItem2); // 2 1 0 - List_append(heads[2], &testItem2); // 0 1 2 - List_prepend(heads[3], &testItem2); // 2 1 0 - - for(int i=0;i<4;i++) - { - printf("\nPrinting nodes in heads[%d] \n",i); - int j=0; - List_first(heads[i]); - while(heads[i]->current!=NULL) - { - printf("\t Value in Node #%d: %d",j,*(int*)List_curr(heads[i])); - List_next(heads[i]); - j++; - if(j%5==0) - { - printf("\n"); - } - } - printf("\nPrinting head and tail nodes in heads[%d] \n",i); - printf("\tHead of heads[%d] : %d",i,*(int*)heads[i]->head->item); - printf("\tTail of heads[%d] : %d",i,*(int*)heads[i]->tail->item); - printf("\n"); - } - - printf("\nChanging current node into the middle node, and adding 3 to the list with each addition method \n"); - for(int i=0;i<4;i++) - { - List_first(heads[i]); - List_next(heads[i]); - } - int testItem3=3; - List_add(heads[0], &testItem3); //0 1 3 2 - List_insert(heads[1], &testItem3); // 2 3 1 0 - List_append(heads[2], &testItem3); // 0 1 2 3 - List_prepend(heads[3], &testItem3); // 3 2 1 0 - for(int i=0;i<4;i++) - { - printf("\nPrinting nodes in heads[%d] \n",i); - int j=0; - List_first(heads[i]); - while(heads[i]->current!=NULL) - { - printf("\t Value in Node #%d: %d",j,*(int*)List_curr(heads[i])); - List_next(heads[i]); - j++; - if(j%5==0) - { - printf("\n"); - } - } - printf("\n"); - } - - printf("\nTesting additions when current is before start\n"); - for(int i=0;i<4;i++) - { - List_first(heads[i]); - List_prev(heads[i]); - } - int testItem4=4; - List_add(heads[0], &testItem4); //4 0 1 3 2 - List_insert(heads[1], &testItem4); //4 2 3 1 0 - List_append(heads[2], &testItem4); //0 1 2 3 4 - List_prepend(heads[3], &testItem4); //4 3 2 1 0 - for(int i=0;i<4;i++) - { - printf("\nPrinting nodes in heads[%d] \n",i); - int j=0; - List_first(heads[i]); - while(heads[i]->current!=NULL) - { - printf("\t Value in Node #%d: %d",j,*(int*)List_curr(heads[i])); - List_next(heads[i]); - j++; - if(j%5==0) - { - printf("\n"); - } - } - printf("\nPrinting head and tail nodes in heads[%d] \n",i); - printf("\tHead of heads[%d] : %d",i,*(int*)heads[i]->head->item); - printf("\tTail of heads[%d] : %d",i,*(int*)heads[i]->tail->item); - - printf("\n"); - } - - printf("\nTesting additions when current is before start\n"); - for(int i=0;i<4;i++) - { - List_last(heads[i]); - List_next(heads[i]); - } - int testItem5=5; - List_add(heads[0], &testItem5); //4 0 1 3 2 5 - List_insert(heads[1], &testItem5); //4 2 3 1 0 5 - List_append(heads[2], &testItem5); //0 1 2 3 4 5 - List_prepend(heads[3], &testItem5); //5 4 3 2 1 0 - for(int i=0;i<4;i++) - { - printf("\nPrinting nodes in heads[%d] \n",i); - int j=0; - List_first(heads[i]); - while(heads[i]->current!=NULL) - { - printf("\t Value in Node #%d: %d",j,*(int*)List_curr(heads[i])); - List_next(heads[i]); - j++; - if(j%6==0) - { - printf("\n"); - } - } - printf("\nPrinting head and tail nodes in heads[%d] \n",i); - printf("\tHead of heads[%d] : %d",i,*(int*)heads[i]->head->item); - printf("\tTail of heads[%d] : %d",i,*(int*)heads[i]->tail->item); - - printf("\n"); - } - for(int i=0;i<4;i++) - { - printf("Current size of list (expected 6) : %d\n", List_count(heads[i])); - } - - printf("\nDeleting all currently allocated heads \n"); - for (int i=0;i<4;i++) - { - List_free(heads[i],&freeStatic); - } - - printf("\nTesting addition on non available heads \n"); - printf("List_add(heads[0], &testItem5) = %d (expected -1) \n",List_add(heads[0], &testItem5)); //empty - printf("List_insert(heads[1], &testItem5) = %d (expected -1) \n",List_insert(heads[1], &testItem5)); //empty - printf("List_append(heads[2], &testItem5) = %d (expected -1) \n",List_append(heads[2], &testItem5)); //empty - printf("List_prepend(heads[3], &testItem5) = %d (expected -1) \n",List_prepend(heads[3], &testItem5)); //empty -} - -// Testing the node max limits to see if memory management works -void testNodeLimit() -{ - printf("\n\nTesting node limit \n"); - printf("Testing with 1 head \n"); - List* head = List_create(); - int testItems[102]; - for (int i=0;i<102;i++) - { - testItems[i]=i; - } - printf("Adding 100 nodes containing ints 0 to 99 to the head \n"); - for (int i=0;i<100;i++) - { - List_add(head, &testItems[i]); - } - - printf("Attempting to add ints 100 and 101 to the head \n"); - List_add(head, &testItems[100]); - List_add(head, &testItems[101]); - - printf("Printing the items in the nodes in the array \n"); - int i=0; - List_first(head); - while(head->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head)); - List_next(head); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Expected result : no node with item 100 and 101 \n"); - - printf("Deleting the list \n"); - List_free(head,&freeStatic); - - printf("\n\nTesting with multiple heads \n"); - printf("Creating 10 heads \n"); - List* heads[10]; - for (int i=0;i<10;i++) - { - heads[i]=List_create(); - } - - printf("Populating each of the 10 heads with 10 nodes\n"); - for(int i=0;i<100;i++) - { - List_add(heads[i/10],&testItems[i]); - } - - printf("Attempting to add one node to each head with item 100\n"); - for(int i=0;i<10;i++) - { - List_add(heads[i], &testItems[100]); - } - - for(int i=0;i<10;i++) - { - printf("Printing nodes in heads[%d] \n",i); - int j=0; - List_first(heads[i]); - while(heads[i]->current!=NULL) - { - printf("\t Value in Node #%d: %d",j,*(int*)List_curr(heads[i])); - List_next(heads[i]); - j++; - if(j%5==0) - { - printf("\n"); - } - } - printf("\n"); - } - - printf("Expected: No node with item 100\n"); - - printf("\nDeleting all currently allocated heads \n"); - for (i=0;i<10;i++) - { - List_free(heads[i],&freeStatic); - } -} - -// Testing removal functions: List_remove, List_trim -void testRemovalFunctions() -{ - printf("\n\nTesting node removal functions\n"); - printf("\nTesting removing empty lists \n"); - List* head; - head = List_create(); - printf("List_remove(head) : %p (expected NULL) \n",List_remove(head)); - printf("List_trim(head) : %p (expected NULL) \n",List_trim(head)); - - printf("\nAdding 0 to 10 to the list\n"); - int testItems[10]; - for (int i=0;i<10;i++) - { - testItems[i]=i; - List_add(head, &testItems[i]); - } - int i=0; - List_first(head); - while(head->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head)); - List_next(head); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("Current size of list (expected 10) : %d\n", List_count(head)); - printf("\n"); - - printf("Current node is in beyond end\n"); - printf("List_remove(head) : %p (expected NULL) \n",List_remove(head)); - printf("*(int*)List_trim(head) : %d (expected 9) \n",*(int*)List_trim(head)); - printf("Tail after trimming: %d (expected 8) \n",*(int*)List_last(head)); - printf("Current size of list (expected 9) : %d\n", List_count(head)); - - printf("\nMoving current node to be before start \n"); - List_first(head); - List_prev(head); - printf("List_remove(head) : %p (expected NULL) \n",List_remove(head)); - printf("*(int*)List_trim(head) : %d (expected 8) \n",*(int*)List_trim(head)); - printf("Tail after trimming: %d (expected 7) \n",*(int*)List_last(head)); - printf("Current size of list (expected 8) : %d\n", List_count(head)); - - printf("\nMoving current node to start\n"); - printf("Head before removing: %d (expected 0) \n",*(int*)List_first(head)); - printf("List_remove(head) : %d (expected 0) \n",*(int*)List_remove(head)); - printf("Head after removing: %d (expected 1) \n",*(int*)List_first(head)); - printf("Current size of list (expected 7) : %d\n", List_count(head)); - - printf("\nMoving current node to end\n"); - printf("Tail before removing: %d (expected 7) \n",*(int*)List_last(head)); - printf("List_remove(head) : %d (expected 7) \n",*(int*)List_remove(head)); - printf("Tail after removing: %d (expected 6) \n",*(int*)List_last(head)); - printf("Current size of list (expected 6) : %d\n", List_count(head)); - - printf("\nPrinting current list\n"); - i=0; - List_first(head); - while(head->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head)); - List_next(head); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("Current size of list (expected 6) : %d\n", List_count(head)); - printf("\n"); - - printf("\nMoving current node to the third node (item stored 3)\n"); - List_first(head); - List_next(head); - printf("Third node before removing: %d (expected 3) \n",*(int*)List_next(head)); - printf("List_remove(head) : %d (expected 3) \n",*(int*)List_remove(head)); - - printf("\nPrinting current list after third node removal\n"); - i=0; - List_first(head); - while(head->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head)); - List_next(head); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("Current size of list (expected 5) : %d\n", List_count(head)); - - printf("\nDeleting all currently allocated heads \n"); - List_free(head,&freeStatic); -} - -// Testing List_concat -void testConcat() -{ - printf("\nTesting List_concat\n"); - printf("\nTesting concat with 2 empty heads\n"); - printf("Creating 2 empty heads\n"); - List* head1=List_create(); - List* head2=List_create(); - printf("Concatenating both empty heads \n"); - List_concat(head1,head2); - printf("\tTo test whether or not head2 no longer exists, we create 9 more heads\n"); - printf("\tIf all 9 heads are successfully created, then List_concat properly removes head2\n"); - List* heads[10]; - for (int i=0;i<10;i++) - { - heads[i]=List_create(); - if(i<9) - { - printf("heads[%d] = %p (expected not NULL)\n",i,heads[i]); - } - else - { - printf("heads[%d] = %p (expected NULL)\n",i,heads[i]); - } - } - printf("\nDeleting the temporary array heads[] \n"); - for (int i=0;i<10;i++) - { - if(heads[i]!=NULL) - { - List_free(heads[i],&freeStatic); - } - } - - printf("\nTesting concat of non-empty head1 and empty head2\n"); - head2=List_create(); - printf("Adding 0 and 1 to head1\n"); - int testItems[10]; - for (int i=0;i<10;i++) - { - testItems[i]=i; - } - List_add(head1, &testItems[0]); - List_add(head1, &testItems[1]); - - printf("\nPrinting head1\n"); - int i=0; - List_first(head1); - while(head1->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head1)); - List_next(head1); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Current size of list (expected 2) : %d\n", List_count(head1)); - - printf("\nConcatenating head1 with empty head2\n"); - List_concat(head1,head2); - - printf("\nPrinting head1 after concatenating with empty head2\n"); - i=0; - List_first(head1); - while(head1->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head1)); - List_next(head1); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Current size of list (expected 2) : %d\n", List_count(head1)); - - printf("\tTo test whether or not head2 no longer exists, we create 9 more heads\n"); - printf("\tIf all 9 heads are successfully created, then List_concat properly removes head2\n"); - for (int i=0;i<10;i++) - { - heads[i]=List_create(); - if(i<9) - { - printf("heads[%d] = %p (expected not NULL)\n",i,heads[i]); - } - else - { - printf("heads[%d] = %p (expected NULL)\n",i,heads[i]); - } - } - printf("\nDeleting the temporary array heads[] \n"); - for (int i=0;i<10;i++) - { - if(heads[i]!=NULL) - { - List_free(heads[i],&freeStatic); - } - } - - printf("\nTesting concat of empty head1 and non-empty head2\n"); - List_free(head1,&freeStatic); - head1=List_create(); - head2=List_create(); - printf("Adding 0 and 1 to head2 \n"); - List_add(head2, &testItems[0]); - List_add(head2, &testItems[1]); - - printf("\nPrinting head2\n"); - i=0; - List_first(head2); - while(head2->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head2)); - List_next(head2); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Current size of list (expected 2) : %d\n", List_count(head2)); - - printf("\nConcatenating empty head1 with non-empty head2\n"); - List_concat(head1,head2); - - printf("\nPrinting the previously empty head1 after concatenating with non-empty head2\n"); - i=0; - List_first(head1); - while(head1->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head1)); - List_next(head1); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Current size of list (expected 2) : %d\n", List_count(head1)); - - printf("head1 = %p\n",head1); - - printf("\tTo test whether or not head2 no longer exists, we create 9 more heads\n"); - printf("\tIf all 9 heads are successfully created, then List_concat properly removes head2\n"); - for (int i=0;i<10;i++) - { - heads[i]=List_create(); - if(i<9) - { - printf("heads[%d] = %p (expected not NULL)\n",i,heads[i]); - } - else - { - printf("heads[%d] = %p (expected NULL)\n",i,heads[i]); - } - } - printf("\nDeleting the temporary array heads[] \n"); - for (int i=0;i<10;i++) - { - if(heads[i]!=NULL) - { - List_free(heads[i],&freeStatic); - } - } - - printf("\nConcatenating non-empty head1 with non-empty head2\n"); - List_free(head1,&freeStatic); - List_free(head2,&freeStatic); - head1=List_create(); - head2=List_create(); - printf("Adding 0 and 1 to head1 and 2 3 to head2"); - List_add(head1,&testItems[0]); - List_add(head1,&testItems[1]); - List_add(head2,&testItems[2]); - List_add(head2,&testItems[3]); - - printf("\nPrinting head1\n"); - i=0; - List_first(head1); - while(head1->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head1)); - List_next(head1); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Current size of list (expected 2) : %d\n", List_count(head1)); - - printf("\nPrinting head2\n"); - i=0; - List_first(head2); - while(head2->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head2)); - List_next(head2); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Current size of list (expected 1) : %d\n", List_count(head2)); - - printf("\nMoving current of head1 to tail of head1\n"); - printf("Current node of head1 is : %d\n",*(int*)List_last(head1)); - printf("\nConcatenating head1 and head2\n"); - List_concat(head1,head2); - - printf("Checking current node of head 1: %d (expected 1)\n",*(int*)List_curr(head1)); - - printf("\nPrinting head1 after concatenation with head2\n"); - i=0; - List_first(head1); - while(head1->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head1)); - List_next(head1); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("\n"); - printf("Current size of list (expected 4) : %d\n", List_count(head1)); - - printf("\nDeleting all currently allocated heads \n"); - List_free(head1,&freeStatic); - List_free(head2,&freeStatic); -} - -// Testing List_search -void testSearch() -{ - int i; - printf("\nTesting List_search\n"); - printf("\nCreating testItems[10] with values 0 to 9\n"); - int testItems[10]; - for(int i=0;i<10;i++) - { - testItems[i]=i; - } - printf("Testing with empty head\n"); - List* head=List_create(); - printf("List_search(head, &compareInt, &testItems[0]) = %p (expected NULL)\n",List_search(head, &compareInt, &testItems[0])); - - printf("\nPopulating the list with 0-9\n"); - for (int i=0;i<10;i++) - { - List_add(head, &testItems[i]); - } - - printf("\nPrinting head\n"); - i=0; - List_first(head); - while(head->current!=NULL) - { - printf("Value in Node #%d : %d ",i,*(int*)List_curr(head)); - List_next(head); - i++; - if(i%5==0) - { - printf("\n"); - } - } - printf("Current size of list (expected 10) : %d\n", List_count(head)); - - printf("\nMoving current node to beyond end and testing List_search\n"); - List_last(head); - List_next(head); - printf("List_search(head, &compareInt, &testItems[0]) = %p (expected NULL)\n",List_search(head, &compareInt, &testItems[0])); - - printf("\nMoving current node to before start and searching for 5\n"); - int test5=5; - List_first(head); - List_prev(head); - printf("*(int*)List_search(head, &compareInt, &test5) = %d (expected 5)\n",*(int*)List_search(head, &compareInt, &test5)); - printf("*(int*)List_curr(head) = %d (expected 5)\n",*(int*)List_curr(head)); - - printf("\nSearching for 8\n"); - int test8=8; - printf("*(int*)List_search(head, &compareInt, &test5) = %d (expected 8)\n",*(int*)List_search(head, &compareInt, &test8)); - printf("*(int*)List_curr(head) = %d (expected 8)\n",*(int*)List_curr(head)); - - printf("\nSearching for 5 which is behind current\n"); - printf("List_search(head, &compareInt, &test5) = %p (expected NULL)\n",List_search(head, &compareInt, &test5)); - printf("List_curr(head) = %p (expected NULL)\n",List_curr(head)); - printf("head->oob = %d (expected 1 (oob end) )\n",head->oob); - - printf("\nDeleting all currently allocated heads \n"); - List_free(head,&freeStatic); -} - -int main () -{ - testHeadRelated(); - printf("\n------------------------------------------------------\n"); - testListCount(); - printf("\n------------------------------------------------------\n"); - testListTraversal(); - printf("\n------------------------------------------------------\n"); - testListAddition(); - printf("\n------------------------------------------------------\n"); - testNodeLimit(); - printf("\n------------------------------------------------------\n"); - testRemovalFunctions(); - printf("\n------------------------------------------------------\n"); - testConcat(); - printf("\n------------------------------------------------------\n"); - testSearch(); - - return 0; -} \ No newline at end of file diff --git a/output -sTalk b/output -sTalk deleted file mode 100644 index c419ce9..0000000 --- a/output -sTalk +++ /dev/null @@ -1,22 +0,0 @@ -// make file - -FLAGS = -Wall -Werror - -all: - build - -build: - gcc $(FLAGS) launcher.c readInput.c writeOutput.c sendUDP.c receiveUDP.c -pthread -o s-Talk - -run: - build - ./s-Talk - - -valgrind: - build - valgrind --leak-check=full ./s-Talk - - -clean: - rm -f s-Talk \ No newline at end of file diff --git a/queueOperations.c b/queueOperations.c new file mode 100644 index 0000000..87764a6 --- /dev/null +++ b/queueOperations.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +#include"queueOperations.h" +#include"list.h" + +static pthread_mutex_t queueMutex = PTHREAD_MUTEX_INITIALIZER; + +void enqueueMessage(List* list, char* message) +{ + pthread_mutex_lock(&queueMutex); + { + int prepVal = List_prepend(list, message); + if(prepVal==-1) + { + fprintf(stderr, "Enqueue failed, queue full"); + } + } + pthread_mutex_unlock(&queueMutex); +} +char* dequeueMessage(List* list) +{ + char* message; + pthread_mutex_lock(&queueMutex); + { + message = List_trim(list); + if(message == NULL) + { + fprintf(stderr, "Dequeue failed, queue empty"); + } + } + pthread_mutex_unlock(&queueMutex); + + return message; +} + +int countMessages(List* list) +{ + int count; + pthread_mutex_lock(&queueMutex); + { + count = List_count(list); + } + pthread_mutex_unlock(&queueMutex); + + return count; +} \ No newline at end of file diff --git a/queueOperations.h b/queueOperations.h new file mode 100644 index 0000000..c4aa45e --- /dev/null +++ b/queueOperations.h @@ -0,0 +1,13 @@ +#ifndef _QUEUE_OPERATIONS_H +#define _QUEUE_OPERATIONS_H + +#include "list.h" + +// Manages the shared queue operations +// Creates mutexes for both operations + +void enqueueMessage(List* list, char* message); +char* dequeueMessage(List* list); +int countMessages(List* list); + +#endif \ No newline at end of file diff --git a/read.c b/read.c deleted file mode 100755 index f23eede..0000000 --- a/read.c +++ /dev/null @@ -1,66 +0,0 @@ -//screen, -//reads off keyboard and adds to list - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "list.h" -#define MAXBUFLEN 65508 - -static List* list; - -static pthread_t readThread; -static pthread_cond_t ready = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t readyMutex = PTHREAD_MUTEX_INITIALIZER; - - -void readTask(void* useless){ - //read gets called // done - //adds message to list // done - //notify sendUDP that read is ready // done - - - - char bufStorageOfMessage[MAXBUFLEN]; - // bufStorageOfMessage = '\0'; - read(0,bufStorageOfMessage, MAXBUFLEN -1); - List_perpend(list, bufStorageOfMessage); -} - - -void readInit(char* hostname, char* port, List* list){ - - //first read gets called and added to list - int readingThread = pthread_create(&readThread, NULL, readTask, NULL); - if(readingThread <= 0){//if gave error of -1 or 0 for false - perror("read thread failed"); - } - - //signaling sendUPD - //wrapping the signal in locks - pthread_mutex_lock(&readyMutex); // acquire a lock on the mutex - { - //signal// - pthread_cond_signal(&ready); - } - pthread_mutex_unlock(&readyMutex); // unlocks the mutex - - -} - - - -int main(int argCount,char* args[]){ - - - -} diff --git a/read.o b/read.o deleted file mode 100644 index a1a873d..0000000 Binary files a/read.o and /dev/null differ diff --git a/readInput.c b/readInput.c index 696ad2d..4c38ba3 100644 --- a/readInput.c +++ b/readInput.c @@ -4,12 +4,16 @@ #include #include #include +#include #include "list.h" #include "queueOperations.h" #include "readInput.h" +#include "sendUDP.h" +#include "threadCanceller.h" -#define MAXBUFLEN 65508 +// Max size of the message, using theoretical max length for a UDP packet +#define MAXBUFLEN 3 // 65506 static List* list; static pthread_t readerThread; @@ -20,30 +24,44 @@ static void* readLoop(void* useless){ // Declaring variables char* message; char bufStorageOfMessage[MAXBUFLEN]; - - // Reading user input - int numbytes = read(0,bufStorageOfMessage, MAXBUFLEN); - if(numbytes==-1) + int numbytes; + int iteration = 0; + do { - perror("reader: read() failed"); - exit(-1); - } - - // Downsizing the size of the message to be more space efficient - message = (char*)malloc(sizeof(char)*(numbytes)); - strncpy(message, bufStorageOfMessage, numbytes); - // Note: we don't need null terminator here because we're going to send the result, not print it - // Our receiver will add the null terminator for us - - // TODO: CREATE A COND VAR SUCH THAT AFTER READ, IMMEDIATELY SEND - - // Adding the message to the list - enqueueMessage(list, message); - + iteration++; + + // Emptying input string buffer + memset(&bufStorageOfMessage, 0, MAXBUFLEN); + // Reading user input + numbytes = read(0,bufStorageOfMessage, MAXBUFLEN); + if(numbytes==-1) + { + perror("reader: read() failed"); + exit(-1); + } + + // Downsizing the size of the message to be more space efficient + message = (char*)malloc(sizeof(char)*(numbytes+1)); + strncpy(message, bufStorageOfMessage, numbytes); + message[numbytes] = '\0'; + + // Adding the message to the list + enqueueMessage(list, message); + + // Checking for exit code + // Ends the process if exit code was in the first iteration of read + if (!strcmp(message,"!\n") && iteration==1) + { + senderSignaller(); + cancelReceiverWriter(); + return NULL; + } + } while (bufStorageOfMessage[numbytes-1]!='\n'); + +printf("reader: number of input right now = %d\n",countMessages(list)); +printf("reader: number of chunks to send = %d\n", iteration); //send signal for the senderUDP - sendSignaller(); - - + senderSignaller(); } return NULL; @@ -61,11 +79,12 @@ void readerInit(List* l){ } -void readerShutdown() +void readerCancel() { pthread_cancel(readerThread); - pthread_join(readerThread,NULL); } - - +void readerShutdown() +{ + pthread_join(readerThread,NULL); +} diff --git a/readInput.h b/readInput.h new file mode 100644 index 0000000..782df1f --- /dev/null +++ b/readInput.h @@ -0,0 +1,13 @@ +#ifndef _READ_INPUT_H +#define _READ_INPUT_H + +#include "list.h" + +// Reads input from the keyboard +// Starts a new pthread + +void readerInit(List* l); +void readerShutdown(); +void readerCancel(); + +#endif \ No newline at end of file diff --git a/receiveUDP.c b/receiveUDP.c new file mode 100644 index 0000000..4852a73 --- /dev/null +++ b/receiveUDP.c @@ -0,0 +1,170 @@ +// Code is adapted (not copied) from Brian Fraser's Workshops and Beej's Guide to Network Programming examples +// IPv4 is exclusively used here + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "list.h" +#include "queueOperations.h" +#include "writeOutput.h" +#include "receiveUDP.h" +#include "threadCanceller.h" + +// Max size of the message, using theoretical max length for a UDP packet +#define MAXBUFLEN 3 // 65506 + +// Preparing variables we'll use +static int sockfd; +static struct addrinfo *servinfo; +static char* myPort; +static List* list; +static pthread_t receiverThread; + +static void* receiverLoop (void* unused) +{ + // Preparing variables we'll use + int sockfd; + struct addrinfo hints, *servinfo, *p; + int gaiVal; + int bindVal; + int numbytes; + char buf[MAXBUFLEN]; + char* message; + struct sockaddr_in their_addr; + socklen_t addr_len; + + // Setting up the hints addrinfo for the getaddrinfo function + memset(&hints, 0 ,sizeof (hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + + // Getting address information with getaddrinfo + // Listening on our machine, on myPort + gaiVal = getaddrinfo(NULL, myPort, &hints, &servinfo); + + // Error checking for getaddrinfo + if (gaiVal != 0 ) + { + fprintf(stderr, "receiver: getaddrinfo error: %s\n", gai_strerror(gaiVal)); + exit(-1); + } + + // Initializing a socket and binding it to any port we find + // Doing a for loop because getaddrinfo generates a linked list of addrinfos + for(p = servinfo; p!=NULL; p=p->ai_next) + { + sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + + // Error checking for socket + if (sockfd ==-1) + { + perror("receiver: socket() error"); + continue; + } + + bindVal = bind(sockfd, p->ai_addr, p->ai_addrlen); + + // Error checking for bind + if(bindVal ==-1) + { + close(sockfd); + perror("receiver: bind() error"); + continue; + } + break; + } + + // Error checking if no sockets are binded + if(p==NULL) + { + fprintf(stderr, "receiver: failed to bind socket"); + exit(-1); + } + + // Freeing our results from getaddrinfo + freeaddrinfo(servinfo); + + while(1) + { + int iteration = 0; + do + { + iteration++; + + // Emptying out receiving buffer + memset(&buf, 0, MAXBUFLEN); + + // Receiving + addr_len = sizeof(their_addr); + numbytes = recvfrom(sockfd, buf, MAXBUFLEN, 0, (struct sockaddr* ) &their_addr, &addr_len); + + // Error checking recvfrom + if(numbytes ==-1) + { + perror("receiver: recvfrom error"); + exit(-1); + } + + // Copying buf to a smaller string to put to the list + message = (char*)malloc(sizeof(char)*(numbytes+1)); + strncpy(message, buf, numbytes); + message[numbytes] = '\0'; + + // Adding message to the list + enqueueMessage(list, message); + + // Checking for exit code + // Ends the process if exit code was in the first iteration of receive + if(!strcmp(message, "!\n") && iteration == 1) + { + writerSignaller(); + cancelReaderSender(); + return NULL; + } + } while (buf[numbytes-1]!='\n'); + +printf("receiver: number of input right now = %d\n",countMessages(list)); +printf("receiver: number of chunks to write = %d\n", iteration); + // Signals writer to write message to screen + writerSignaller(); + } + return NULL; +} + +void receiverInit(char* myP, List* l) +{ + myPort = myP; + list = l; + + int rectVal = pthread_create(&receiverThread, NULL, receiverLoop, NULL); + if(rectVal != 0) + { + perror("sender: thread creation error"); + exit(-1); + } +} + +void receiverCancel() +{ + pthread_cancel(receiverThread); +} +void receiverShutdown() +{ + // Freeing our results from getaddrinfo + freeaddrinfo(servinfo); + + // closing connection to the socket + close(sockfd); + + pthread_join(receiverThread, NULL); +} \ No newline at end of file diff --git a/receiveUDP.h b/receiveUDP.h new file mode 100644 index 0000000..221941e --- /dev/null +++ b/receiveUDP.h @@ -0,0 +1,14 @@ +#ifndef _RECEIVE_UDP_H +#define _RECEIVE_UDP_H + +#include "list.h" + +// Receives a string through connectionless UDP +// IPv4 is exclusively used +// Starts a new pthread + +void receiverInit(char* myP, List* l); +void receiverShutdown(); +void receiverCancel(); + +#endif \ No newline at end of file diff --git a/sendUDP.c b/sendUDP.c index 4ee1e2d..b2c7ffd 100644 --- a/sendUDP.c +++ b/sendUDP.c @@ -1,6 +1,5 @@ // Code is adapted (not copied) from Brian Fraser's Workshops and Beej's Guide to Network Programming examples // IPv4 is exclusively used here - #include #include #include @@ -14,14 +13,14 @@ #include #include "list.h" -#include "queueOperations.h" // in another branch +#include "queueOperations.h" #include "sendUDP.h" //Preparing variables to use static int sockfd; static struct addrinfo *servinfo; -static char* hostname; -static char* port; +static char* theirHostname; +static char* theirPort; static List* list; static pthread_t senderThread; static char* message; @@ -33,115 +32,138 @@ static pthread_cond_t sendAvailableCond = PTHREAD_COND_INITIALIZER; // initlizin static void* senderLoop(void* unused) { - struct addrinfo hints, *p; - int gaiVal; - int bindVal; - int numbytes; - // Setting up the hints addrinfo for the getaddrinfo function - memset(&hints, 0 ,sizeof (hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - - //Getting address information with getaddrinfo - gaiVal = getaddrinfo(hostname, port, &hints, &servinfo); - // Error checking for getaddrinfo - if (gaiVal != 0 ) - { - fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(gaiVal)); - exit(-1); - } - - // Initializing a socket and binding it to any port we find - // Doing a for loop because getaddrinfo generates a linked list of addrinfos - for(p = servinfo; p!=NULL; p=p->ai_next) - { - sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - - // Error checking for socket - if (sockfd ==-1) - { - perror("sender: socket() error"); - continue; - } - break; - } - // Error checking if no sockets are binded - if(p==NULL) - { - fprintf(stderr, "sender: failed to create socket"); - exit(-1); - } - - while(1) - { - // Getting message from list - - - //Waits until notified by the sendSignaller = pthread_cond_wait - pthread_cond_lock(&sendAvailableCond); - { - pthread_cond_wait(&sendAvailableCond, &sendAvailableCondMutex); - } - pthread_cond_unlock(&sendAvailableCond); - - - // Sending - numbytes = sendto(sockfd, message, strlen(message), 0, p->ai_addr, p->ai_addrlen); - - // De-allocating message - free(message); - message = NULL; - - // Error checking recvfrom - if(numbytes ==-1) - { - perror("sender: sendto error"); - exit(-1); - } - } - return NULL; + struct addrinfo hints, *p; + int gaiVal; + int numbytes; + // Setting up the hints addrinfo for the getaddrinfo function + memset(&hints, 0 ,sizeof (hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + + // Getting address information with getaddrinfo + // Sending to theirHostname, on theirPort + gaiVal = getaddrinfo(theirHostname, theirPort, &hints, &servinfo); + // Error checking for getaddrinfo + if (gaiVal != 0 ) + { + fprintf(stderr, "sender: getaddrinfo error: %s\n", gai_strerror(gaiVal)); + exit(-1); + } + + // Initializing a socket and binding it to any port we find + // Doing a for loop because getaddrinfo generates a linked list of addrinfos + for(p = servinfo; p!=NULL; p=p->ai_next) + { + sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + + // Error checking for socket + if (sockfd ==-1) + { + perror("sender: socket() error"); + continue; + } + break; + } + // Error checking if no sockets are binded + if(p==NULL) + { + fprintf(stderr, "sender: failed to create socket"); + exit(-1); + } + + while(1) + { + //Waits until notified by the senderSignaller = pthread_cond_wait + pthread_mutex_lock(&sendAvailableCondMutex); + { + pthread_cond_wait(&sendAvailableCond, &sendAvailableCondMutex); + } + pthread_mutex_unlock(&sendAvailableCondMutex); + + int iteration = 0; + printf("sender: number of items to send = %d\n", countMessages(list)); + + do + { + iteration++; + + // Getting message from list + message = dequeueMessage(list); + + // Sending + numbytes = sendto(sockfd, message, strlen(message), 0, p->ai_addr, p->ai_addrlen); + + // Check for exit code + // Ends the thread if exit code is passed in the first iteration of the read + if(!strcmp(message,"!\n") && iteration==1) + { + free(message); + message = NULL; + return NULL; + } + + // De-allocating message + free(message); + message = NULL; + + // Error checking recvfrom + if(numbytes ==-1) + { + perror("sender: sendto error"); + exit(-1); + } + } while (countMessages(list)!=0); + +printf("sender: number of items in list after send = %d\n", countMessages(list)); +printf("sender: number of items sent= %d\n", iteration); + } + return NULL; } -void sendSignaller(){ +void senderSignaller(){ - //Signals other thread,send thread, waiting on condition variable - pthread_mutex_lock(&sendAvailableCondMutex); - { - pthread_cond_signal(&sendAvailableCond); // signals another thread waiting - } - pthread_mutex_unlock(&sendAvailableCondMutex); + //Signals other thread,send thread, waiting on condition variable + pthread_mutex_lock(&sendAvailableCondMutex); + { + pthread_cond_signal(&sendAvailableCond); // signals another thread waiting + } + pthread_mutex_unlock(&sendAvailableCondMutex); } - + +void senderCancel() +{ + pthread_cancel(senderThread); +} void senderInit(char* hostnm, char* p, List* l) { - hostname=hostnm; - port = p; - list = l; - - int stVal = pthread_create(&senderThread, NULL, senderLoop, NULL); - if(stVal != 0) - { - perror("sender: thread creation error"); - exit(-1); - } + theirHostname=hostnm; + theirPort = p; + list = l; + + int stVal = pthread_create(&senderThread, NULL, senderLoop, NULL); + if(stVal != 0) + { + perror("sender: thread creation error"); + exit(-1); + } } void senderShutdown() { - // De-allocating dynamically allocated message if shutdown is called while message is not yet freed - // Note: if we HAVE already freed the pointer, then we've set the message pointer to NULL - // and it is okay to free a NULL pointer (it does nothing) - free(message); - - // Freeing our results from getaddrinfo - freeaddrinfo(servinfo); - - // closing connection to the socket - close(sockfd); - - pthread_cancel(senderThread); - pthread_join(senderThread, NULL); + // De-allocating dynamically allocated message if shutdown is called while message is not yet freed + // Note: if we HAVE already freed the pointer, then we've set the message pointer to NULL + // and it is okay to free a NULL pointer (it does nothing) + free(message); + message=NULL; + + // Freeing our results from getaddrinfo + freeaddrinfo(servinfo); + + // closing connection to the socket + close(sockfd); + + pthread_join(senderThread, NULL); } \ No newline at end of file diff --git a/sendUDP.h b/sendUDP.h index 14b6cb1..433256d 100644 --- a/sendUDP.h +++ b/sendUDP.h @@ -8,8 +8,8 @@ // Starts a new pthread void senderInit(char* hostnm, char* p, List* l); +void senderCancel(); void senderShutdown(); -void sendSignaller(); -static void* senderLoop(void* unused); +void senderSignaller(); #endif \ No newline at end of file diff --git a/threadCanceller.c b/threadCanceller.c new file mode 100644 index 0000000..a264303 --- /dev/null +++ b/threadCanceller.c @@ -0,0 +1,16 @@ +#include "readInput.h" +#include "writeOutput.h" +#include "sendUDP.h" +#include "receiveUDP.h" +#include "threadCanceller.h" + +void cancelReceiverWriter() +{ + receiverCancel(); + writerCancel(); +} +void cancelReaderSender() +{ + readerCancel(); + senderCancel(); +} \ No newline at end of file diff --git a/threadCanceller.h b/threadCanceller.h new file mode 100644 index 0000000..3a837c5 --- /dev/null +++ b/threadCanceller.h @@ -0,0 +1,7 @@ +#ifndef _THREAD_CANCELLER_H +#define _THREAD_CANCELLER_H + +void cancelReceiverWriter(); +void cancelReaderSender(); + +#endif \ No newline at end of file diff --git a/write.c b/write.c deleted file mode 100644 index 3359635..0000000 --- a/write.c +++ /dev/null @@ -1,69 +0,0 @@ -//keyboard, -// take list message and write to screen - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "list.h" -#define MAXBUFLEN 65508 - -static List* list; - -//brians vid on synchronozayion -static pthread_t writeThread; -static pthread_cond_t readyW = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t readyWMutex = PTHREAD_MUTEX_INITIALIZER; - - -void writeTask(void* useless){ - - int writeVar = write(1,List_trim(list), MAXBUFLEN ); // will put the message from first list onto screen - if(writeVar == -1){ - perror("Error in write() : Unable to write to screen"); - - } -} - - -void writeInit(char* hostname, char* port, List* list){ - - //before write gets called needs to wait// - //wait until signalled// - pthread_mutex_lock(&readyWMutex); // acquire a lock on the mutex - { - //signal// - pthread_cond_wait(&readyW,&readyWMutex);// mutex will release while - } - pthread_mutex_unlock(&readyWMutex); // unlocks the mutex - - - //the condition it needs to check for if it was called from reciever - //if so then proceed to do the write - - - int writingThread = pthread_create(&writeThread, NULL, writeTask, NULL); - if(writingThread != 0){ - perror("Error: write thread failed"); - } - - //once done// - pthread_join(writingThread, NULL); - -} - - - -int main(int argCount,char* args[]){ - - write(1,"Test", 4); // this works! - -} diff --git a/write.o b/write.o deleted file mode 100644 index dfa8133..0000000 Binary files a/write.o and /dev/null differ diff --git a/writeOutput.c b/writeOutput.c index 07cea6c..7759673 100644 --- a/writeOutput.c +++ b/writeOutput.c @@ -1,106 +1,108 @@ -// using part of Darrn's check + addrino info since its more accurate - +// take list message and write to screen #include #include -#include -#include #include -#include -#include -#include -#include -#include +#include +#include #include "list.h" +#include "queueOperations.h" +#include "writeOutput.h" -// Max size of the message, theoretical max size of a UDP packet in IPv4. -#define MAXBUFLEN 65508 - -// variable set up -static int sockRead; -static struct addrinfo hints, *servinfo, *p; -static int gaiVal; -static int bindVal; -static int readBytes; -char buf[MAXBUFLEN]; -static struct sockaddr_in their_addr; -static socklen_t messageLen; -static char s[INET_ADDRSTRLEN]; -char* message; - -void receiverInit(char* hostname, char* port, List* list) -{ +// Max size of the message, using theoretical max length for a UDP packet +#define MAXBUFLEN 3 // 65506 - //set up - memset(&hints, 0 ,sizeof (hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; +static pthread_t writerThread; +static pthread_mutex_t writeAvailableCondMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t writeAvailableCond = PTHREAD_COND_INITIALIZER; +static List* list; +static char* message; - //using Darren's non hard coded values - gaiVal = getaddrinfo(hostname, port, &hints, &servinfo); +static void* writeLoop(void* useless){ - // Error checking for getaddrinfo - if (gaiVal != 0 ) - { - fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(gaiVal)); - return; - } - - //crating socket + checks - for(p = servinfo; p!=NULL; p=p->ai_next) + while(1) { - sockRead = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - // Error checking for socket - if (sockRead ==-1) + // Waits the write funtion, will be signalled by receiveUDP + pthread_mutex_lock(&writeAvailableCondMutex); { - perror("receiver: socket() error"); - continue; + pthread_cond_wait(&writeAvailableCond, &writeAvailableCondMutex); } + pthread_mutex_unlock(&writeAvailableCondMutex); + + int iteration = 0; +printf("writer: number of items to write = %d\n", countMessages(list)); - // binding socket - bindVal = bind(sockRead, p->ai_addr, p->ai_addrlen); - // Error checking for bind - if(bindVal ==-1) + do { - close(sockRead); - perror("receiver: bind() error in receiver"); - continue; - } - break; + iteration ++; + + // Taking message from list + message = dequeueMessage(list); + + int writeVar = write(1,message, strlen(message)); // will put the message from first list onto screen + if(writeVar == -1){ + perror("Error in write() : Unable to write to screen"); + exit(-1); + } + + // Checking for exit code + if(!strcmp(message, "!\n") && iteration == 1) + { + free(message); + message = NULL; + return NULL; + } + + // Freeing message (message is dynamically allocated from receiver) + free(message); + message = NULL; + } while (countMessages(list)!=0); + +printf("writer: number of items in list after write = %d\n", countMessages(list)); +printf("writer: number of items written = %d\n", iteration); } + return NULL; + +} - // Error checking if no sockets are binded - if(p==NULL) +void writerSignaller() +{ + //Signals the writer, will be called by receiveUDP + pthread_mutex_lock(&writeAvailableCondMutex); { - fprintf(stderr, "receiver: failed to bind socket"); - return; + pthread_cond_signal(&writeAvailableCond); } + pthread_mutex_unlock(&writeAvailableCondMutex); +} - // Freeing our results from getaddrinfo - freeaddrinfo(servinfo); - - while(1) - { - // Receiving - messageLen = sizeof(their_addr); - write(sockRead, buf, MAXBUFLEN); - buf[readBytes]='\0'; // not sure what this does +void writerInit(List* l){ - // adding buff to list, - message = (char*)malloc(sizeof(char)*(readBytes+1)); // allocates space for new item - strncpy(message, buf, readBytes); - message[readBytes] = '\0'; //not sure what this does + list = l; - // Adding message to the front of list - List_prepend(list, message); + int writingThread = pthread_create(&writerThread, NULL, writeLoop, NULL); + if(writingThread != 0){ + perror("write thread failed"); + exit(-1); } } -void receiverShutdown() + +void writerCancel() { - close(sockRead); -} \ No newline at end of file + pthread_cancel(writerThread); +} + +void writerShutdown() +{ + // De-allocating dynamically allocated message if shutdown is called while message is not yet freed + // Note: if we HAVE already freed the pointer, then we've set the message pointer to NULL + // and it is okay to free a NULL pointer (it does nothing) + free(message); + message = NULL; + + pthread_join(writerThread, NULL); +} + diff --git a/writeOutput.h b/writeOutput.h new file mode 100644 index 0000000..e57c595 --- /dev/null +++ b/writeOutput.h @@ -0,0 +1,14 @@ +#ifndef _WRITE_OUTPUT_H +#define _WRITE_OUTPUT_H + +#include "list.h" + +// Writer module, will print to the screen +// Starts a new pthread + +void writerSignaller(); +void writerInit(List* l); +void writerCancel(); +void writerShutdown(); + +#endif \ No newline at end of file