63b70c3903feea369c927fae63b7eef9c7f92741
[carveJwlIkooP6JGAAIwe30JlM.git] / network.c
1 #include "player.h"
2 #include "network.h"
3
4 static void scores_update(void);
5
6 static void on_auth_ticket_recieved( void *result, void *context ){
7 EncryptedAppTicketResponse_t *response = result;
8
9 if( response->m_eResult == k_EResultOK ){
10 vg_info( " New app ticket ready\n" );
11 }
12 else{
13 vg_warn( " Could not request new encrypted app ticket (%u)\n",
14 response->m_eResult );
15 }
16
17 if( SteamAPI_ISteamUser_GetEncryptedAppTicket( hSteamUser,
18 network_client.app_symmetric_key,
19 vg_list_size(network_client.app_symmetric_key),
20 &network_client.app_key_length )){
21 vg_success( " Loaded app ticket\n" );
22 }
23 else{
24 vg_error( " No ticket availible\n" );
25 network_client.app_key_length = 0;
26 }
27 }
28
29 static void request_auth_ticket(void){
30 /*
31 * TODO Check for one thats cached on the disk and load it.
32 * This might be OK though because steam seems to cache the result
33 */
34
35 vg_info( "Requesting new authorization ticket\n" );
36
37 vg_steam_async_call *call = vg_alloc_async_steam_api_call();
38 call->userdata = NULL;
39 call->p_handler = on_auth_ticket_recieved;
40 call->id =
41 SteamAPI_ISteamUser_RequestEncryptedAppTicket( hSteamUser, NULL, 0 );
42 }
43
44 static void send_auth_ticket(void){
45 u32 size = sizeof(netmsg_auth) + network_client.app_key_length;
46 netmsg_auth *auth = alloca(size);
47
48 auth->inetmsg_id = k_inetmsg_auth;
49 auth->ticket_length = network_client.app_key_length;
50 for( int i=0; i<network_client.app_key_length; i++ )
51 auth->ticket[i] = network_client.app_symmetric_key[i];
52
53 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
54 hSteamNetworkingSockets, network_client.remote, auth, size,
55 k_nSteamNetworkingSend_Reliable, NULL );
56 }
57
58 static void send_score_request(void){
59 vg_info( "Requesting scores\n" );
60 netmsg_scores_request req;
61 req.inetmsg_id = k_inetmsg_scores_request;
62
63 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
64 hSteamNetworkingSockets, network_client.remote,
65 &req, sizeof(netmsg_scores_request),
66 k_nSteamNetworkingSend_Reliable, NULL );
67 }
68
69 static void send_score_update(void){
70 vg_info( "Sending scores\n" );
71 u32 size = sizeof(netmsg_set_score) +
72 vg_list_size(track_infos)*sizeof(struct netmsg_score_record);
73 netmsg_set_score *setscore = alloca( size );
74 setscore->inetmsg_id = k_inetmsg_set_score;
75
76 int count = 0;
77 for( u32 i=0; i<vg_list_size(track_infos); i++ ){
78 if( track_infos[i].push ){
79 track_infos[i].push = 0;
80
81 #if 0
82 highscore_record *user_record = highscore_find_user_record( 0, i );
83
84 if( !user_record ){
85 vg_error( "No score set but tried to upload for track %u\n", i );
86 continue;
87 }
88 #endif
89 highscore_record *user_record = &track_infos[i].record;
90
91 setscore->records[count].trackid = i;
92 setscore->records[count].playerid = 0;
93 setscore->records[count].points = user_record->points;
94 setscore->records[count].time = user_record->time;
95
96 count ++;
97 }
98 }
99
100 if( count == 0 ) return;
101 u32 send_size = sizeof(netmsg_set_score) +
102 count*sizeof(struct netmsg_score_record);
103 setscore->record_count = count;
104
105 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
106 hSteamNetworkingSockets, network_client.remote, setscore, send_size,
107 k_nSteamNetworkingSend_Reliable, NULL );
108 }
109
110 static void send_nickname(void){
111 netmsg_set_nickname nick;
112 nick.inetmsg_id = k_inetmsg_set_nickname;
113
114 memset( nick.nickname, 0, 16 );
115 vg_strncpy( steam_username_at_startup, nick.nickname, 16,
116 k_strncpy_allow_cutoff );
117
118 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
119 hSteamNetworkingSockets, network_client.remote,
120 &nick, sizeof(netmsg_set_nickname),
121 k_nSteamNetworkingSend_Reliable, NULL );
122
123 network_client.name_update = 0;
124 }
125
126 static void network_send_playerframe(void){
127 netmsg_playerframe frame;
128 frame.inetmsg_id = k_inetmsg_playerframe;
129 v3_copy( localplayer.rb.co, frame.pos_temp );
130
131 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
132 hSteamNetworkingSockets, network_client.remote,
133 &frame, sizeof(frame),
134 k_nSteamNetworkingSend_Unreliable, NULL );
135 }
136
137 static void server_routine_update(void){
138 if( network_client.name_update )
139 send_nickname();
140
141 send_score_update();
142 send_score_request();
143 }
144
145 static void on_server_connect_status( CallbackMsg_t *msg ){
146 SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
147 vg_info( " Connection status changed for %lu\n", info->m_hConn );
148 vg_info( " %s -> %s\n",
149 string_ESteamNetworkingConnectionState(info->m_eOldState),
150 string_ESteamNetworkingConnectionState(info->m_info.m_eState) );
151
152 if( info->m_hConn == network_client.remote ){
153 network_client.state = info->m_info.m_eState;
154 if( info->m_info.m_eState == k_ESteamNetworkingConnectionState_Connected ){
155 vg_success(" Connected to remote server.. authenticating\n");
156 send_auth_ticket();
157 }
158 }
159 else{
160 vg_warn( " Recieved signal from unknown connection\n" );
161 }
162 }
163
164 static void network_connect(void){
165 /* Connect to server if not connected */
166 SteamNetworkingIPAddr remoteAddr;
167
168 #ifdef SR_USE_LOCALHOST
169 SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( &remoteAddr, 27402 );
170 #else
171 const char *server_lon1 = "46.101.34.155:27402";
172 SteamAPI_SteamNetworkingIPAddr_ParseString( &remoteAddr, server_lon1 );
173 #endif
174
175 char buf[256];
176 SteamAPI_SteamNetworkingIPAddr_ToString( &remoteAddr, buf, 256, 1 );
177 vg_info( "connect to: %s\n", buf );
178
179 network_client.remote = SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress(
180 hSteamNetworkingSockets, &remoteAddr, 0, NULL );
181 }
182
183 static void on_inet_scoreboard( SteamNetworkingMessage_t *msg ){
184 netmsg_scoreboard *sb = msg->m_pData;
185
186 u32 base_size = sizeof(netmsg_scoreboard)-
187 sizeof(struct netmsg_board)*vg_list_size(track_infos),
188 expected = base_size+sizeof(struct netmsg_board)*sb->board_count;
189
190 if( msg->m_cbSize != expected ){
191 vg_error( "Server scoreboard was corrupted. Size: %u != %u\n",
192 msg->m_cbSize, expected );
193 }
194 else{
195 if( vg_list_size(track_infos) > sb->board_count )
196 vg_warn( "Server is out of date, not enough boards recieved\n");
197 else if( vg_list_size(track_infos) < sb->board_count )
198 vg_warn( "Client out of date, server sent more boards than we have\n");
199 else
200 vg_success( "Recieved new scoreboards from server\n" );
201
202 for( int i=0; i < vg_min(sb->board_count,vg_list_size(track_infos)); i++){
203 scoreboard_client_data.boards[i] = sb->boards[i];
204 highscores_board_printf( stdout, sb->boards[i].data, 10 );
205 }
206 }
207
208 /* We dont need to stay on the server currently */
209 SteamAPI_ISteamNetworkingSockets_CloseConnection(
210 hSteamNetworkingSockets, network_client.remote, 0, NULL, 1 );
211
212 network_scores_updated = 1;
213 }
214
215 static void poll_remote_connection(void){
216 SteamNetworkingMessage_t *messages[32];
217 int len;
218
219 for( int i=0; i<10; i++ ){
220 len = SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection(
221 hSteamNetworkingSockets, network_client.remote,
222 messages, vg_list_size(messages));
223
224 if( len <= 0 )
225 return;
226
227 for( int i=0; i<len; i++ ){
228 SteamNetworkingMessage_t *msg = messages[i];
229
230 if( msg->m_cbSize < sizeof(netmsg_blank) ){
231 vg_warn( "Discarding message (too small: %d)\n", msg->m_cbSize );
232 continue;
233 }
234
235 netmsg_blank *tmp = msg->m_pData;
236
237 if( tmp->inetmsg_id == k_inetmsg_scoreboard )
238 on_inet_scoreboard( msg );
239
240 SteamAPI_SteamNetworkingMessage_t_Release( msg );
241 }
242 }
243 }
244
245 static void network_update(void){
246 if( !steam_ready )
247 return;
248
249 ESteamNetworkingConnectionState state = network_client.state;
250
251 if( state == k_ESteamNetworkingConnectionState_Connected ){
252 poll_remote_connection();
253 f64 frame_delta = vg.time_real - network_client.last_frame;
254
255 if( frame_delta > 0.1 ){
256 network_client.last_frame = vg.time_real;
257 network_send_playerframe();
258 }
259 }
260 else {
261 if( (state == k_ESteamNetworkingConnectionState_Connecting) ||
262 (state == k_ESteamNetworkingConnectionState_FindingRoute) ){
263 return;
264 }
265 else {
266 f64 waited = vg.time_real - network_client.last_attempt,
267 min_wait = 1.0;
268
269 if( network_client.retries > 5 )
270 min_wait = 60.0;
271
272 if( waited < min_wait )
273 return;
274
275 network_connect();
276 network_client.retries ++;
277 network_client.last_attempt = vg.time_real;
278 }
279 }
280 }
281
282 static void network_init(void){
283 if( steam_ready ){
284 steam_register_callback( k_iSteamNetConnectionStatusChangedCallBack,
285 on_server_connect_status );
286 request_auth_ticket();
287 }
288 }
289
290 static void network_end(void){
291 /* TODO: Send buffered highscores that were not already */
292 if( (network_client.state == k_ESteamNetworkingConnectionState_Connected) ||
293 (network_client.state == k_ESteamNetworkingConnectionState_Connecting) )
294 {
295 SteamAPI_ISteamNetworkingSockets_CloseConnection(
296 hSteamNetworkingSockets, network_client.remote, 0, NULL, 1 );
297 }
298 }