[sylverant] r766 committed - Some changes to a few things in shipgate. Foreshadowing of things to c...

4 views
Skip to first unread message

sylv...@googlecode.com

unread,
Dec 29, 2014, 4:19:13 PM12/29/14
to sylverant-...@googlegroups.com
Revision: 766
Author: bluecrab
Date: Mon Dec 29 21:18:55 2014 UTC
Log: Some changes to a few things in shipgate. Foreshadowing of things
to come soon. ;-)


https://code.google.com/p/sylverant/source/detail?r=766

Modified:
/trunk/shipgate/src/packets.c
/trunk/shipgate/src/ship.c
/trunk/shipgate/src/ship.h
/trunk/shipgate/src/shipgate.c
/trunk/shipgate/src/shipgate.h

=======================================
--- /trunk/shipgate/src/packets.c Sat Dec 13 05:26:28 2014 UTC
+++ /trunk/shipgate/src/packets.c Mon Dec 29 21:18:55 2014 UTC
@@ -68,9 +68,8 @@
tmp = realloc(c->sendbuf, c->sendbuf_cur + rv);

/* If we can't allocate the space, bail. */
- if(tmp == NULL) {
+ if(tmp == NULL)
return -1;
- }

c->sendbuf_size = c->sendbuf_cur + rv;
c->sendbuf = (unsigned char *)tmp;
@@ -87,9 +86,8 @@
/* Encrypt a packet, and send it away. */
static int send_crypt(ship_t *c, int len) {
/* Make sure its at least a header in length. */
- if(len < 8) {
+ if(len < 8)
return -1;
- }

return send_raw(c, len);
}
@@ -224,9 +222,8 @@
shipgate_ship_status6_pkt *pkt = (shipgate_ship_status6_pkt *)sendbuf;

/* If the ship hasn't finished logging in yet, don't send this. */
- if(o->name[0] == 0) {
+ if(o->name[0] == 0)
return 0;
- }

/* Scrub the buffer */
memset(pkt, 0, sizeof(shipgate_ship_status6_pkt));
@@ -265,12 +262,10 @@
pkt->reserved = 0;
pkt->version = 0;

- if(reply) {
+ if(reply)
pkt->flags = htons(SHDR_RESPONSE);
- }
- else {
+ else
pkt->flags = 0;
- }

/* Send it away. */
return send_crypt(c, sizeof(shipgate_hdr_t));
@@ -346,16 +341,10 @@
const uint8_t *data, int data_sz) {
shipgate_error_pkt *pkt = (shipgate_error_pkt *)sendbuf;
uint16_t sz;
-
- /* These were first added in protocol version 1. */
- if(c->proto_ver < 1) {
- return 0;
- }

/* Make sure the data size is valid */
- if(data_sz > 65536 - sizeof(shipgate_error_pkt)) {
+ if(data_sz > 65536 - sizeof(shipgate_error_pkt))
return -1;
- }

/* Clear the header of the packet */
memset(pkt, 0, sizeof(shipgate_error_pkt));
@@ -427,9 +416,8 @@
pkt->guildcard = htonl(user);
pkt->block = htonl(block);

- if(reason) {
+ if(reason)
strncpy(pkt->reason, reason, 64);
- }

/* Send the packet away */
return send_crypt(c, sizeof(shipgate_kick_pkt));
@@ -531,9 +519,8 @@
uint16_t len = pkt->hdr.pkt_len;

/* Make sure we have something to send, at least */
- if(!pkt->count) {
+ if(!pkt->count)
return 0;
- }

/* Swap that which we need to do */
pkt->hdr.pkt_len = htons(len);
=======================================
--- /trunk/shipgate/src/ship.c Fri Nov 14 03:29:48 2014 UTC
+++ /trunk/shipgate/src/ship.c Mon Dec 29 21:18:55 2014 UTC
@@ -62,6 +62,10 @@
extern gnutls_certificate_credentials_t tls_cred;
extern gnutls_priority_t tls_prio;

+/* Events... */
+extern uint32_t event_count;
+extern monster_event_t *events;
+
static uint8_t recvbuf[65536];

/* Find a ship by its id */
@@ -115,6 +119,38 @@
buf[14] = (uint8_t)(lo >> 8);
buf[15] = (uint8_t)lo;
}
+
+static monster_event_t *find_current_event(uint8_t difficulty, uint8_t
ver) {
+ uint32_t i;
+ uint8_t questing;
+ time_t now;
+
+ /* For now, just reject any challenge/battle mode updates... We don't
care
+ about them at all. */
+ if(ver & 0xC0)
+ return NULL;
+
+ now = time(NULL);
+ questing = ver & 0x20;
+ ver &= 0x07;
+
+ for(i = 0; i < event_count; ++i) {
+ /* Skip all quests that don't meet the requirements passed in. */
+ if(now > events[i].end_time || now < events[i].start_time)
+ continue;
+ if(!(events[i].versions & (1 << ver)))
+ continue;
+ if(!(events[i].difficulties & (1 << difficulty)))
+ continue;
+ if(!events[i].allow_quests && questing)
+ continue;
+
+ /* If we get here, then the event is valid, return it. */
+ return events + i;
+ }
+
+ return NULL;
+}

/* Create a new connection, storing it in the list of ships. */
ship_t *create_connection_tls(int sock, struct sockaddr *addr, socklen_t
size) {
@@ -178,7 +214,8 @@

/* Check whether or not the peer is trusted... */
if(peer_status & GNUTLS_CERT_INVALID) {
- debug(DBG_WARN, "Untrusted peer connection, reason below:\n");
+ debug(DBG_WARN, "Untrusted peer connection, reason below
(%08x):\n",
+ peer_status);

if(peer_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
debug(DBG_WARN, "No issuer found\n");
@@ -2890,6 +2927,7 @@
case USER_OPT_QUEST_LANG:
case USER_OPT_ENABLE_BACKUP:
case USER_OPT_GC_PROTECT:
+ case USER_OPT_TRACK_KILLS:
/* The full option should be 16 bytes */
if(optlen != 16) {
return -4;
@@ -2998,6 +3036,22 @@
int i;
void *result;
char **row;
+ monster_event_t *ev;
+
+ printf("got monster kill packet\n");
+
+ /* Ignore any packets that aren't version 1 or later. They're useless.
*/
+ if(pkt->hdr.version < 1)
+ return 0;
+
+ printf("didn't drop\n");
+
+ /* See if there's an event currently running, otherwise we can safely
drop
+ any monster kill packets we get. */
+ if(!(ev = find_current_event(pkt->difficulty, pkt->version)))
+ return 0;
+
+ printf("got current event\n");

/* Parse out the guildcard */
gc = ntohl(pkt->guildcard);
@@ -3035,6 +3089,7 @@
/* If their account id in the table is NULL, then bail. No need to
report an
error for this. */
if(!row[0]) {
+ printf("no account\n");
sylverant_db_result_free(result);
return 0;
}
@@ -3043,9 +3098,39 @@
acc = atoi(row[0]);
sylverant_db_result_free(result);

- /* Ignore these for now for most people... :P */
- if(acc != 1)
+ /* Are we recording all monsters, or just a few? */
+ if(ev->monster_count) {
+ printf("have monsters\n");
+ for(i = 0; i < ev->monster_count; ++i) {
+ printf("looking for monster %d\n", ev->monsters[i].monster);
+ if(ev->monsters[i].monster > 0x60)
+ continue;
+
+ ct = ntohl(pkt->counts[ev->monsters[i].monster]);
+ printf("got count of %d\n", (int)ct);
+
+ if(!ct || pkt->episode != ev->monsters[i].episode)
+ continue;
+
+ sprintf(query, "INSERT INTO monster_kills (account_id,
guildcard, "
+ "episode, difficulty, enemy, count) VALUES('%"
PRIu32 "', "
+ "'%" PRIu32 "', '%u', '%u', '%d', '%" PRIu32"') ON "
+ "DUPLICATE KEY UPDATE count=count+VALUES(count)", acc,
gc,
+ (unsigned int)pkt->episode, (unsigned
int)pkt->difficulty,
+ i, ct);
+
+ /* Execute the query */
+ if(sylverant_db_query(&conn, query)) {
+ debug(DBG_WARN, "%s\n", sylverant_db_error(&conn));
+ return send_error(c, SHDR_TYPE_MKILL, SHDR_FAILURE,
+ ERR_BAD_ERROR, (uint8_t
*)&pkt->guildcard, 8);
+ }
+ }
+
return 0;
+ }
+
+ printf("no monsters listed\n");

/* Go through each entry... */
for(i = 0; i < 0x60; ++i) {
=======================================
--- /trunk/shipgate/src/ship.h Sat Nov 12 03:30:27 2011 UTC
+++ /trunk/shipgate/src/ship.h Mon Dec 29 21:18:55 2014 UTC
@@ -51,6 +51,24 @@
char name[32];
} PACKED friendlist_data_t;

+typedef struct event_monster {
+ uint16_t monster;
+ uint8_t episode;
+ uint8_t reserved;
+} PACKED event_monster_t;
+
+typedef struct monster_event {
+ uint32_t event_id;
+ char *event_title;
+ uint32_t start_time;
+ uint32_t end_time;
+ uint8_t difficulties;
+ uint8_t versions;
+ uint8_t allow_quests;
+ uint32_t monster_count;
+ event_monster_t *monsters;
+} monster_event_t;
+
#undef PACKED

typedef struct ship {
=======================================
--- /trunk/shipgate/src/shipgate.c Sat Mar 29 22:50:30 2014 UTC
+++ /trunk/shipgate/src/shipgate.c Mon Dec 29 21:18:55 2014 UTC
@@ -56,6 +56,10 @@

int shutting_down = 0;

+/* Events... */
+uint32_t event_count;
+monster_event_t *events;
+
static const char *config_file = NULL;
static const char *custom_dir = NULL;
static int dont_daemonize = 0;
@@ -72,7 +76,7 @@
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
the\n"
"GNU General Public License for more details.\n\n"
"You should have received a copy of the GNU Affero General
Public\n"
- "License along with this program. If not, see"
+ "License along with this program. If not, see\n"
"<http://www.gnu.org/licenses/>.\n");
}

@@ -175,6 +179,178 @@
gnutls_priority_deinit(tls_prio);
gnutls_global_deinit();
}
+
+static void free_events() {
+ uint32_t i;
+
+ for(i = 0; i < event_count; ++i) {
+ free(events[i].monsters);
+ }
+
+ free(events);
+}
+
+static int read_events_table() {
+ void *result;
+ char **row;
+ long long row_count, i, row_count2, j;
+ char query[256];
+
+ debug(DBG_LOG, "Reading events from the database...\n");
+ if(sylverant_db_query(&conn, "SELECT event_id, title, start_time, "
+ "end_time, difficulties, versions, "
+ "allow_quests FROM monster_events WHERE "
+ "end_time > UNIX_TIMESTAMP() ORDER BY "
+ "start_time")) {
+ debug(DBG_WARN, "Couldn't fetch events from database!\n");
+ return -1;
+ }
+
+ if((result = sylverant_db_result_store(&conn)) == NULL) {
+ debug(DBG_WARN, "Could not store results of event select!\n");
+ return -1;
+ }
+
+ /* Make sure we have something. */
+ row_count = sylverant_db_result_rows(result);
+ if(row_count < 0) {
+ debug(DBG_WARN, "Couldn't fetch event count!\n");
+ sylverant_db_result_free(result);
+ return -1;
+ }
+ else if(!row_count) {
+ debug(DBG_LOG, "No events in database.\n");
+ sylverant_db_result_free(result);
+ return 0;
+ }
+
+ /* Allocate space for the events... */
+ events = (monster_event_t *)malloc(row_count *
sizeof(monster_event_t));
+ if(!events) {
+ debug(DBG_WARN, "Error allocating memory for events!\n");
+ sylverant_db_result_free(result);
+ return -1;
+ }
+
+ memset(events, 0, row_count * sizeof(monster_event_t));
+ event_count = (uint32_t)row_count;
+
+ /* Save each one. */
+ i = 0;
+ while((row = sylverant_db_result_fetch(result))) {
+ /* This shouldn't ever happen... but whatever, doesn't hurt to
check. */
+ if(i >= row_count) {
+ debug(DBG_WARN, "Got more result rows than expected?!\n");
+ sylverant_db_result_free(result);
+ free(events);
+ return -1;
+ }
+
+ /* Copy the data over. */
+ events[i].event_id = strtoul(row[0], NULL, 0);
+ events[i].start_time = strtoul(row[2], NULL, 0);
+ events[i].end_time = strtoul(row[3], NULL, 0);
+ events[i].difficulties = (uint8_t)strtoul(row[4], NULL, 0);
+ events[i].versions = (uint8_t)strtoul(row[5], NULL, 0);
+ events[i].allow_quests = (uint8_t)strtoul(row[6], NULL, 0);
+
+ if(!(events[i].event_title = strdup(row[1]))) {
+ debug(DBG_WARN, "Error copying event title!\n");
+ sylverant_db_result_free(result);
+ free(events);
+ return -1;
+ }
+
+ ++i;
+ }
+
+ sylverant_db_result_free(result);
+
+ if(i < row_count) {
+ debug(DBG_WARN, "Got less result rows than expected?!\n");
+ free(events);
+ return -1;
+ }
+
+ /* Run through each event and read the monster lists... */
+ for(i = 0; i < row_count; ++i) {
+ sprintf(query, "SELECT monster_type, episode FROM "
+ "monster_event_monsters WHERE event_id= '%"
PRIu32 "'",
+ events[i].event_id);
+
+ if(sylverant_db_query(&conn, query)) {
+ debug(DBG_WARN, "Couldn't fetch monsters from database!\n");
+ free_events();
+ return -1;
+ }
+
+ if((result = sylverant_db_result_store(&conn)) == NULL) {
+ debug(DBG_WARN, "Could not store results of monster select!");
+ free_events();
+ return -1;
+ }
+
+ /* Make sure we have something. */
+ row_count2 = sylverant_db_result_rows(result);
+ events[i].monster_count = (uint32_t)row_count2;
+
+ debug(DBG_LOG, "Event ID %" PRIu32 " (%s) - %" PRIu32 "
enemies.\n",
+ events[i].event_id, events[i].event_title,
+ events[i].monster_count);
+
+ if(row_count2 == 0) {
+ sylverant_db_result_free(result);
+ continue;
+ }
+ /* This shouldn't happen, but check anyway... */
+ else if(row_count2 < 0 || row_count2 > 256) {
+ sylverant_db_result_free(result);
+ debug(DBG_WARN, "Got less than zero monsters in event?!\n");
+ free_events();
+ return -1;
+ }
+
+ /* Allocate space for the monsters... */
+ events[i].monsters =
+ (event_monster_t *)malloc(row_count2 *
sizeof(event_monster_t));
+ if(!events[i].monsters) {
+ debug(DBG_WARN, "Error allocating memory for monsters!\n");
+ sylverant_db_result_free(result);
+ free_events();
+ return -1;
+ }
+
+ memset(events[i].monsters, 0, row_count2 *
sizeof(event_monster_t));
+
+ j = 0;
+ while((row = sylverant_db_result_fetch(result))) {
+ /* Once again, shouldn't happen, but check anyway... */
+ if(j >= row_count2) {
+ debug(DBG_WARN, "Got more result rows than expected?!\n");
+ sylverant_db_result_free(result);
+ free_events();
+ return -1;
+ }
+
+ events[i].monsters[j].monster = (uint16_t)strtoul(row[0],
NULL, 0);
+ events[i].monsters[j].episode = (uint8_t)strtoul(row[1], NULL,
0);
+ ++j;
+ }
+
+ sylverant_db_result_free(result);
+
+ /* Same warning about it shouldn't happen applies here... */
+ if(j < row_count2) {
+ debug(DBG_WARN, "Got less result rows than expected?!\n");
+ free_events();
+ return -1;
+ }
+ }
+
+ debug(DBG_LOG, "Read %" PRIu32 " events successfully.\n", event_count);
+
+ return 0;
+}

static void open_db() {
debug(DBG_LOG, "Connecting to the database...\n");
@@ -195,6 +371,10 @@
debug(DBG_ERROR, "Error clearing online_clients\n");
exit(EXIT_FAILURE);
}
+
+ if(read_events_table()) {
+ exit(EXIT_FAILURE);
+ }
}

void run_server(int tsock, int tsock6) {
@@ -269,7 +449,7 @@
if(tsock6 > -1) {
FD_SET(tsock6, &readfds);
nfds = nfds > tsock6 ? nfds : tsock6;
- }
+ }

if(select(nfds + 1, &readfds, &writefds, NULL, &timeout) > 0) {
/* Check each ship's socket for activity. */
@@ -423,13 +603,13 @@
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
-
+
if(bind(sock, (struct sockaddr *)&addr, sizeof(struct
sockaddr_in))) {
perror("bind");
close(sock);
return -1;
}
-
+
if(listen(sock, 10)) {
perror("listen");
close(sock);
@@ -556,6 +736,7 @@
/* Clean up. */
close(tsock);
close(tsock6);
+ free_events();
iconv_close(ic_utf8_to_utf16);
iconv_close(ic_utf16_to_utf8);
sylverant_db_close(&conn);
=======================================
--- /trunk/shipgate/src/shipgate.h Sat Mar 29 22:50:30 2014 UTC
+++ /trunk/shipgate/src/shipgate.h Mon Dec 29 21:18:55 2014 UTC
@@ -388,14 +388,17 @@
sylverant_bb_db_opts_t opts;
} PACKED shipgate_bb_opts_pkt;

-/* Packet used to send an update to the user's monster kill counts. */
+/* Packet used to send an update to the user's monster kill counts.
+ Version 1 adds a client version code where there used to be a reserved
byte
+ in the packet. */
typedef struct shipgate_mkill {
shipgate_hdr_t hdr;
uint32_t guildcard;
uint32_t block;
uint8_t episode;
uint8_t difficulty;
- uint8_t reserved[2];
+ uint8_t version;
+ uint8_t reserved;
uint32_t counts[0x60];
} PACKED shipgate_mkill_pkt;

@@ -485,11 +488,26 @@
#define USER_OPT_QUEST_LANG 0x00000001
#define USER_OPT_ENABLE_BACKUP 0x00000002
#define USER_OPT_GC_PROTECT 0x00000003
+#define USER_OPT_TRACK_KILLS 0x00000004

/* Possible values for the fw_flags on a forwarded packet */
#define FW_FLAG_PREFER_IPV6 0x00000001 /* Prefer IPv6 on reply */
#define FW_FLAG_IS_PSOPC 0x00000002 /* Client is on PSOPC */

+/* Possible values for versions in packets that need them. This list
should be
+ kept in-sync with those in clients.h from ship_server. */
+#define CLIENT_VERSION_DCV1 0
+#define CLIENT_VERSION_DCV2 1
+#define CLIENT_VERSION_PC 2
+#define CLIENT_VERSION_GC 3
+#define CLIENT_VERSION_EP3 4
+#define CLIENT_VERSION_BB 5
+
+/* Not a version, but potentially ORed with a version... */
+#define CLIENT_QUESTING 0x20
+#define CLIENT_CHALLENGE_MODE 0x40
+#define CLIENT_BATTLE_MODE 0x80
+
/* Send a welcome packet to the given ship. */
int send_welcome(ship_t *c);

Reply all
Reply to author
Forward
0 new messages