begin network integration
[carveJwlIkooP6JGAAIwe30JlM.git] / network.h
1 #ifndef NETWORK_H
2 #define NETWORK_H
3
4 #include "vg/vg_stdint.h"
5 #include "steam.h"
6 #include "network_msg.h"
7
8 /*
9 * Interface
10 */
11
12 /* Call it at start; Connects us to the gameserver */
13 static void network_init(void);
14
15 /* Run this from main loop */
16 static void network_update(void);
17
18 /* Call it at shutdown */
19 static void network_end(void);
20
21 /*
22 * Can buffer up a bunch of these by calling many times, they will be
23 * sent at the next connection
24 */
25 static void network_submit_highscore( u32 trackid, u16 points, u16 time );
26
27
28 /*
29 * Game endpoints are provided with the same names to allow running without a
30 * network connection.
31 */
32 #ifdef SR_NETWORKED
33
34 /*
35 * Runtime connection stuff
36 */
37 static u8 steam_app_ticket[ 1024 ];
38 static u32 steam_app_ticket_length;
39
40 static HSteamNetConnection cremote;
41 static ESteamNetworkingConnectionState cremote_state =
42 k_ESteamNetworkingConnectionState_None;
43
44 /*
45 * Implementation
46 */
47
48 static void scores_update(void);
49
50 static void on_auth_ticket_recieved( void *result, void *context )
51 {
52 EncryptedAppTicketResponse_t *response = result;
53
54 if( response->m_eResult == k_EResultOK )
55 {
56 vg_info( " New app ticket ready\n" );
57 }
58 else
59 {
60 vg_warn( " Could not request new encrypted app ticket (%u)\n",
61 response->m_eResult );
62 }
63
64 if( SteamAPI_ISteamUser_GetEncryptedAppTicket( hSteamUser,
65 steam_app_ticket,
66 vg_list_size(steam_app_ticket),
67 &steam_app_ticket_length ))
68 {
69 vg_success( " Loaded app ticket (%u bytes)\n", steam_app_ticket_length );
70 }
71 else
72 {
73 vg_error( " No ticket availible\n" );
74 steam_app_ticket_length = 0;
75 }
76 }
77
78 static void request_auth_ticket(void)
79 {
80 /*
81 * TODO Check for one thats cached on the disk and load it.
82 * This might be OK though because steam seems to cache the result
83 */
84
85 vg_info( "Requesting new authorization ticket\n" );
86 steam_async *call = steam_new_async();
87 call->data = NULL;
88 call->p_handler = on_auth_ticket_recieved;
89 call->id = SteamAPI_ISteamUser_RequestEncryptedAppTicket( hSteamUser,
90 NULL, 0 );
91 }
92
93 static void server_connect(void)
94 {
95 /* Connect to server if not connected */
96
97 SteamNetworkingIPAddr remoteAddr;
98
99 #define USE_LOCALHOST
100 #ifdef USE_LOCALHOST
101 SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( &remoteAddr, 27402 );
102 #else
103 const char *server_lon1 = "46.101.34.155:27402";
104 SteamAPI_SteamNetworkingIPAddr_ParseString( &remoteAddr, server_lon1 );
105 #endif
106
107 char buf[256];
108 SteamAPI_SteamNetworkingIPAddr_ToString( &remoteAddr, buf, 256, 1 );
109 vg_info( "connect to: %s\n", buf );
110
111 cremote = SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress(
112 hSteamNetworkingSockets, &remoteAddr, 0, NULL );
113 }
114
115 static void scores_update(void)
116 {
117 vg_log( "scores_update()\n" );
118
119 if( cremote_state == k_ESteamNetworkingConnectionState_Connected )
120 {
121 /*
122 * request updated scores
123 */
124 netmsg_scores_request req;
125 req.inetmsg_id = k_inetmsg_scores_request;
126
127 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
128 hSteamNetworkingSockets, cremote, &req,
129 sizeof(netmsg_scores_request),
130 k_nSteamNetworkingSend_Reliable, NULL );
131 }
132 else
133 {
134 /*
135 * if we are not connected, make a connection to the server and then in
136 * the future this function will be called again when it is connected
137 */
138 server_connect();
139 }
140 }
141
142 static void poll_connection(void)
143 {
144 SteamNetworkingMessage_t *messages[32];
145 int len;
146
147 while(1)
148 {
149 len = SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection(
150 hSteamNetworkingSockets, cremote, messages, vg_list_size(messages));
151
152 if( len <= 0 )
153 return;
154
155 for( int i=0; i<len; i++ )
156 {
157 SteamNetworkingMessage_t *msg = messages[i];
158
159 if( msg->m_cbSize < sizeof(netmsg_blank) )
160 {
161 vg_warn( "Discarding message (too small: %d)\n",
162 msg->m_cbSize );
163 continue;
164 }
165
166 netmsg_blank *tmp = msg->m_pData;
167 if( tmp->inetmsg_id == k_inetmsg_scores_info )
168 {
169 netmsg_scores_info *info = msg->m_pData;
170 vg_log( "Recieved %u score records\n", info->record_count );
171
172 SteamAPI_ISteamNetworkingSockets_CloseConnection(
173 hSteamNetworkingSockets, cremote, 0, NULL, 1 );
174 cremote_state = k_ESteamNetworkingConnectionState_None;
175 }
176
177 SteamAPI_SteamNetworkingMessage_t_Release( msg );
178 }
179 }
180 }
181
182 static u64 in_server_ticks( double seconds )
183 {
184 return (u64)(seconds / 0.1);
185 }
186
187 static void on_server_connect_status( CallbackMsg_t *msg )
188 {
189 SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
190 vg_info( " Connection status changed for %lu\n", info->m_hConn );
191 vg_info( " %s -> %s\n",
192 string_ESteamNetworkingConnectionState(info->m_info.m_eState),
193 string_ESteamNetworkingConnectionState(info->m_eOldState) );
194
195 if( info->m_hConn == cremote )
196 {
197 cremote_state = info->m_info.m_eState;
198 if( info->m_info.m_eState ==
199 k_ESteamNetworkingConnectionState_Connected )
200 {
201 vg_success(" Connected to remote server\n");
202 scores_update();
203 }
204 }
205 else
206 {
207 vg_warn( " Recieved signal from unknown connection\n" );
208 }
209 }
210
211 static void network_init(void)
212 {
213 if( steam_ready )
214 {
215 steam_register_callback( k_iSteamNetConnectionStatusChangedCallBack,
216 on_server_connect_status );
217 request_auth_ticket();
218 }
219 }
220
221 static void network_update(void)
222 {
223 if( steam_ready )
224 {
225 static double last_update = -9000.0;
226 poll_connection();
227
228 if( vg_time > (last_update + 60.0) )
229 {
230 last_update = vg_time;
231 scores_update();
232 }
233 }
234 }
235
236 static void network_end(void)
237 {
238 /* TODO: Fire off any buffered highscores that need to be setn */
239 }
240
241 #endif
242 #endif /* NETWORK_H */