#include #include #include #include #include #include #include #include #include /* * This is a very read-heavy way to go * It does work */ void examine_server_v1(int fd){ char type; // or uint8_t ssize_t readlen; while(1){ if((readlen = read(fd, &type, 1)) != 1) goto err; if(type == 11){ uint16_t initial_points, stat_limit, description_length; if(recv(fd, &initial_points, 2, MSG_WAITALL) != 2) goto err; if(recv(fd, &stat_limit, 2, MSG_WAITALL) != 2) goto err; if(recv(fd, &description_length, 2, MSG_WAITALL) != 2) goto err; char description[description_length + 1]; if(recv(fd, &description, description_length, MSG_WAITALL) != description_length) goto err; description[description_length] = 0; printf("Game received. \nInitial points: %d\nStat limit: %d\nDescription: %s\n", initial_points, stat_limit, description); printf("Disconnecting, since we finished\n"); return; // What if we wanted to return our game description? } else if(type == 14){ uint8_t major_version, minor_version; uint16_t extension_length; if(read(fd, &major_version, 1) != 1) goto err; if(read(fd, &minor_version, 1) != 1) goto err; if(recv(fd, &extension_length, 2, MSG_WAITALL) != 2) goto err; if(extension_length){ char extensions[extension_length]; if(recv(fd, extensions, extension_length, MSG_WAITALL) != extension_length) goto err; } printf("Connected to lurk server with version %d.%d and %d bytes of extensions\n", major_version, minor_version, extension_length); } else { printf("Received type %d, probably not a lurk server\n", type); return; } } err: printf("Error encountered, giving up\n"); } struct game { uint16_t initial_points, stat_limit, description_length; std::string description; bool read(int fd){ if(recv(fd, this, 6, MSG_WAITALL) != 6) return false; char tmp_description[description_length + 1]; tmp_description[description_length] = 0; if(recv(fd, tmp_description, description_length, MSG_WAITALL) != description_length) return false; description = tmp_description; // Will probably cause a heap allocation return true; } } __attribute__((packed)); struct version{ uint8_t major_version, minor_version; uint16_t extension_length; void send(int fd){ // code that sends ourselves to fd // Send type, next send ourselves with the "this" pointer: // write(fd, this, 4); } bool read(int fd){ return recv(fd, this, sizeof(struct version), MSG_WAITALL) == 4; } } __attribute__((packed)); struct game get_game_struct(int fd){ char type; // or uint8_t struct game g = {0, 0, 0, ""}; ssize_t readlen; while(1){ if((readlen = read(fd, &type, 1)) != 1) goto err; if(type == 14){ struct version v; if(!v.read(fd)) goto err; printf("Connected to lurk server with version %d.%d and %d bytes of extensions\n", v.major_version, v.minor_version, v.extension_length); } else if (type == 11){ g.read(fd); printf("Game received. \nInitial points: %d\nStat limit: %d\nDescription: %s\n", g.initial_points, g.stat_limit, g.description.c_str()); return g; } else { printf("Received type %d, probably not a lurk server\n", type); return g; } } err: printf("Error encountered, giving up\n"); return g; } int main(int argc, char ** argv){ if(argc < 3){ printf("Usage: %s hostname port\n", argv[0]); return 1; } struct sockaddr_in sad; sad.sin_port = htons(atoi(argv[2])); sad.sin_family = AF_INET; printf("port: %d\n", sad.sin_port); int skt = socket(AF_INET, SOCK_STREAM, 0); // do a dns lookup struct hostent* entry = gethostbyname(argv[1]); if(!entry){ if(h_errno == HOST_NOT_FOUND){ printf("This is our own message that says the host wasn't found\n"); } herror("gethostbyname"); return 1; } struct in_addr **addr_list = (struct in_addr**)entry->h_addr_list; // -> is like (*entry).h_addr_list struct in_addr* c_addr = addr_list[0]; char* ip_string = inet_ntoa(*c_addr); sad.sin_addr = *c_addr; // copy the address we found into sad // Finally done with DNS! printf("Connecting to: %s\n", ip_string); if( connect(skt, (struct sockaddr*)&sad, sizeof(struct sockaddr_in)) ){ perror("connect"); return 1; } struct game g = get_game_struct(skt); close(skt); return 0; }