diff options
author | erdgeist <> | 2007-01-24 22:23:18 +0000 |
---|---|---|
committer | erdgeist <> | 2007-01-24 22:23:18 +0000 |
commit | 2f0658a3afa65847c11612bd28a65c8c9cbc8725 (patch) | |
tree | 73b32e138938163f06a0f1a9fed3f199a175d12b | |
parent | bcef9d56a43ff15eb80f0c077adefa94afe60392 (diff) |
Code cleanup reindenting
-rw-r--r-- | opentracker.c | 170 |
1 files changed, 78 insertions, 92 deletions
diff --git a/opentracker.c b/opentracker.c index e8504bc..eea02eb 100644 --- a/opentracker.c +++ b/opentracker.c | |||
@@ -44,33 +44,33 @@ static char fd_debug_space[0x10000]; | |||
44 | static char debug_request[8192]; | 44 | static char debug_request[8192]; |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | static void carp(const char* routine) { | 47 | static void carp(const char* routine ) { |
48 | buffer_puts(buffer_2,routine); | 48 | buffer_puts( buffer_2, routine ); |
49 | buffer_puts(buffer_2,": "); | 49 | buffer_puts( buffer_2, ": " ); |
50 | buffer_puterror(buffer_2); | 50 | buffer_puterror( buffer_2 ); |
51 | buffer_putnlflush(buffer_2); | 51 | buffer_putnlflush( buffer_2 ); |
52 | } | 52 | } |
53 | 53 | ||
54 | static void panic(const char* routine) { | 54 | static void panic( const char* routine ) { |
55 | carp(routine); | 55 | carp( routine ); |
56 | exit(111); | 56 | exit( 111 ); |
57 | } | 57 | } |
58 | 58 | ||
59 | struct http_data { | 59 | struct http_data { |
60 | union { | 60 | union { |
61 | array r; | 61 | array request; |
62 | io_batch batch; | 62 | io_batch batch; |
63 | }; | 63 | }; |
64 | unsigned char ip[4]; | 64 | unsigned char ip[4]; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | int header_complete(struct http_data* r) { | 67 | int header_complete( struct http_data* h ) { |
68 | int l = array_bytes(&r->r), i; | 68 | int l = array_bytes( &h->request ), i; |
69 | const char* c = array_start(&r->r); | 69 | const char* c = array_start( &h->request ); |
70 | 70 | ||
71 | for (i=0; i+1<l; ++i) { | 71 | for( i=0; i+1<l; ++i) { |
72 | if (c[i]=='\n' && c[i+1]=='\n') return i+2; | 72 | if( c[i]=='\n' && c[i+1]=='\n') return i+2; |
73 | if (i+3<l && c[i]=='\r' && c[i+1]=='\n' && c[i+2]=='\r' && c[i+3]=='\n') return i+4; | 73 | if( i+3<l && c[i]=='\r' && c[i+1]=='\n' && c[i+2]=='\r' && c[i+3]=='\n' ) return i+4; |
74 | } | 74 | } |
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
@@ -81,7 +81,7 @@ void sendmallocdata( int64 s, struct http_data *h, char * buffer, size_t size ) | |||
81 | size_t header_size; | 81 | size_t header_size; |
82 | 82 | ||
83 | if( !h ) { free( buffer); return; } | 83 | if( !h ) { free( buffer); return; } |
84 | array_reset(&h->r); | 84 | array_reset( &h->request ); |
85 | 85 | ||
86 | header = malloc( SUCCESS_HTTP_HEADER_LENGTH ); | 86 | header = malloc( SUCCESS_HTTP_HEADER_LENGTH ); |
87 | if( !header ) { free( buffer ); return; } | 87 | if( !header ) { free( buffer ); return; } |
@@ -98,18 +98,20 @@ void sendmallocdata( int64 s, struct http_data *h, char * buffer, size_t size ) | |||
98 | io_wantwrite( s ); | 98 | io_wantwrite( s ); |
99 | } | 99 | } |
100 | 100 | ||
101 | /* whoever sends data is not interested in its input-array */ | ||
102 | void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) { | 101 | void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) { |
103 | size_t written_size; | 102 | size_t written_size; |
104 | 103 | ||
105 | if( h ) array_reset(&h->r); | 104 | /* whoever sends data is not interested in its input-array */ |
105 | if( h ) | ||
106 | array_reset( &h->request ); | ||
107 | |||
106 | written_size = write( s, buffer, size ); | 108 | written_size = write( s, buffer, size ); |
107 | if( ( written_size < 0 ) || ( written_size == size ) ) { | 109 | if( ( written_size < 0 ) || ( written_size == size ) ) { |
108 | #ifdef _DEBUG_FDS | 110 | #ifdef _DEBUG_FDS |
109 | if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" ); | 111 | if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" ); |
110 | fd_debug_space[s] = 0; | 112 | fd_debug_space[s] = 0; |
111 | #endif | 113 | #endif |
112 | free(h); io_close( s ); | 114 | free( h ); io_close( s ); |
113 | } else { | 115 | } else { |
114 | char * outbuf = malloc( size - written_size ); | 116 | char * outbuf = malloc( size - written_size ); |
115 | tai6464 t; | 117 | tai6464 t; |
@@ -128,7 +130,7 @@ void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) { | |||
128 | iob_addbuf_free( &h->batch, outbuf, size - written_size ); | 130 | iob_addbuf_free( &h->batch, outbuf, size - written_size ); |
129 | 131 | ||
130 | // writeable sockets just have a tcp timeout | 132 | // writeable sockets just have a tcp timeout |
131 | taia_uint(&t,0); io_timeout( s, t ); | 133 | taia_uint( &t, 0 ); io_timeout( s, t ); |
132 | io_dontwantread( s ); | 134 | io_dontwantread( s ); |
133 | io_wantwrite( s ); | 135 | io_wantwrite( s ); |
134 | } | 136 | } |
@@ -143,24 +145,7 @@ void httperror(int64 s,struct http_data* h,const char* title,const char* message | |||
143 | senddata(s,h,static_scratch,reply_size); | 145 | senddata(s,h,static_scratch,reply_size); |
144 | } | 146 | } |
145 | 147 | ||
146 | const char* http_header(struct http_data* r,const char* h) { | 148 | void httpresponse( int64 s, struct http_data* h) { |
147 | int i, l = array_bytes(&r->r); | ||
148 | int sl = strlen(h); | ||
149 | const char* c = array_start(&r->r); | ||
150 | |||
151 | for (i=0; i+sl+2<l; ++i) { | ||
152 | if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':') { | ||
153 | c+=i+sl+1; | ||
154 | if (*c==' ' || *c=='\t') ++c; | ||
155 | return c; | ||
156 | } | ||
157 | return 0; | ||
158 | } | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | void httpresponse(int64 s,struct http_data* h) | ||
163 | { | ||
164 | char *c, *data; | 149 | char *c, *data; |
165 | ot_peer peer; | 150 | ot_peer peer; |
166 | ot_torrent *torrent; | 151 | ot_torrent *torrent; |
@@ -169,29 +154,29 @@ void httpresponse(int64 s,struct http_data* h) | |||
169 | unsigned short port = htons(6881); | 154 | unsigned short port = htons(6881); |
170 | size_t reply_size = 0; | 155 | size_t reply_size = 0; |
171 | 156 | ||
172 | array_cat0(&h->r); | 157 | array_cat0( &h->request ); |
173 | c = array_start(&h->r); | 158 | c = array_start( &h->request ); |
174 | 159 | ||
175 | #ifdef _DEBUG_HTTPERROR | 160 | #ifdef _DEBUG_HTTPERROR |
176 | memcpy( debug_request, array_start(&h->r), array_bytes(&h->r) ); | 161 | memcpy( debug_request, array_start( &h->request ), array_bytes( &h->request ) ); |
177 | #endif | 162 | #endif |
178 | 163 | ||
179 | if (byte_diff(c,4,"GET ")) { | 164 | if( byte_diff( c, 4, "GET ") ) { |
180 | e400: | 165 | e400: |
181 | return httperror(s,h,"400 Invalid Request","This server only understands GET."); | 166 | return httperror( s, h, "400 Invalid Request", "This server only understands GET." ); |
182 | } | 167 | } |
183 | 168 | ||
184 | c+=4; | 169 | c+=4; |
185 | for (data=c; *data!=' '&&*data!='\t'&&*data!='\n'&&*data!='\r'; ++data) ; | 170 | for( data = c; *data!=' ' && *data != '\t' && *data != '\n' && *data != '\r'; ++data ) ; |
186 | 171 | ||
187 | if (*data!=' ') goto e400; | 172 | if( *data != ' ' ) goto e400; |
188 | *data=0; | 173 | *data = 0; |
189 | if (c[0]!='/') goto e404; | 174 | if( c[0] != '/' ) goto e404; |
190 | while (*c=='/') ++c; | 175 | while( *c == '/' ) ++c; |
191 | 176 | ||
192 | switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { | 177 | switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { |
193 | case 5: /* scrape ? */ | 178 | case 5: /* stats ? */ |
194 | if (byte_diff(data,5,"stats")) | 179 | if( byte_diff(data,5,"stats")) |
195 | goto e404; | 180 | goto e404; |
196 | scanon = 1; | 181 | scanon = 1; |
197 | mode = STATS_MRTG; | 182 | mode = STATS_MRTG; |
@@ -204,7 +189,7 @@ e400: | |||
204 | case -1: /* error */ | 189 | case -1: /* error */ |
205 | goto e404; | 190 | goto e404; |
206 | case 4: | 191 | case 4: |
207 | if(byte_diff(data,4,"mode")) { | 192 | if( byte_diff(data,4,"mode")) { |
208 | scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); | 193 | scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); |
209 | continue; | 194 | continue; |
210 | } | 195 | } |
@@ -227,7 +212,7 @@ e400: | |||
227 | goto e500; | 212 | goto e500; |
228 | break; | 213 | break; |
229 | case 6: /* scrape ? */ | 214 | case 6: /* scrape ? */ |
230 | if (byte_diff(data,6,"scrape")) | 215 | if( byte_diff( data, 6, "scrape") ) |
231 | goto e404; | 216 | goto e404; |
232 | scanon = 1; | 217 | scanon = 1; |
233 | 218 | ||
@@ -294,7 +279,7 @@ e400_param: | |||
294 | size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | 279 | size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); |
295 | unsigned char ip[4]; | 280 | unsigned char ip[4]; |
296 | if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param; | 281 | if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param; |
297 | OT_SETIP ( &peer, ip ); | 282 | OT_SETIP( &peer, ip ); |
298 | } else | 283 | } else |
299 | scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); | 284 | scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); |
300 | break; | 285 | break; |
@@ -303,7 +288,7 @@ e400_param: | |||
303 | if(!byte_diff(data,4,"port")) { | 288 | if(!byte_diff(data,4,"port")) { |
304 | size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | 289 | size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); |
305 | if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param; | 290 | if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param; |
306 | port = htons( tmp ); OT_SETPORT ( &peer, &port ); | 291 | port = htons( tmp ); OT_SETPORT( &peer, &port ); |
307 | } else if(!byte_diff(data,4,"left")) { | 292 | } else if(!byte_diff(data,4,"left")) { |
308 | size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | 293 | size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); |
309 | if( len <= 0 ) goto e400_param; | 294 | if( len <= 0 ) goto e400_param; |
@@ -386,7 +371,7 @@ e500: | |||
386 | break; | 371 | break; |
387 | default: /* neither *scrape nor announce */ | 372 | default: /* neither *scrape nor announce */ |
388 | e404: | 373 | e404: |
389 | return httperror(s,h,"404 Not Found","No such file or directory."); | 374 | return httperror( s, h, "404 Not Found", "No such file or directory." ); |
390 | } | 375 | } |
391 | 376 | ||
392 | if( reply_size ) { | 377 | if( reply_size ) { |
@@ -408,7 +393,8 @@ e404: | |||
408 | 393 | ||
409 | senddata( s, h, static_scratch + reply_off, reply_size ); | 394 | senddata( s, h, static_scratch + reply_off, reply_size ); |
410 | } else { | 395 | } else { |
411 | if( h ) array_reset(&h->r); | 396 | if( h ) |
397 | array_reset( &h->request ); | ||
412 | #ifdef _DEBUG_FDS | 398 | #ifdef _DEBUG_FDS |
413 | if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" ); | 399 | if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" ); |
414 | fd_debug_space[s] = 0; | 400 | fd_debug_space[s] = 0; |
@@ -476,33 +462,33 @@ void handle_read( int64 clientsocket ) { | |||
476 | 462 | ||
477 | if( l <= 0 ) { | 463 | if( l <= 0 ) { |
478 | if( h ) { | 464 | if( h ) { |
479 | array_reset(&h->r); | 465 | array_reset( &h->request ); |
480 | free(h); | 466 | free( h ); |
481 | } | 467 | } |
482 | #ifdef _DEBUG_FDS | 468 | #ifdef _DEBUG_FDS |
483 | if( !fd_debug_space[clientsocket] ) fprintf( stderr, "close on non-open fd\n" ); | 469 | if( !fd_debug_space[clientsocket] ) fprintf( stderr, "close on non-open fd\n" ); |
484 | fd_debug_space[clientsocket] = 0; | 470 | fd_debug_space[clientsocket] = 0; |
485 | #endif | 471 | #endif |
486 | io_close(clientsocket); | 472 | io_close( clientsocket ); |
487 | return; | 473 | return; |
488 | } | 474 | } |
489 | 475 | ||
490 | array_catb(&h->r,static_scratch,l); | 476 | array_catb( &h->request, static_scratch, l ); |
491 | 477 | ||
492 | #ifdef _DEBUG_HTTPERROR | 478 | #ifdef _DEBUG_HTTPERROR |
493 | memcpy( debug_request, "500!\0", 5 ); | 479 | memcpy( debug_request, "500!\0", 5 ); |
494 | #endif | 480 | #endif |
495 | 481 | ||
496 | if( array_failed(&h->r)) | 482 | if( array_failed( &h->request ) ) |
497 | httperror(clientsocket,h,"500 Server Error","Request too long."); | 483 | httperror( clientsocket, h, "500 Server Error", "Request too long."); |
498 | else if (array_bytes(&h->r)>8192) | 484 | else if( array_bytes( &h->request ) > 8192 ) |
499 | httperror(clientsocket,h,"500 request too long","You sent too much headers"); | 485 | httperror( clientsocket, h, "500 request too long", "You sent too much headers"); |
500 | else if ((l=header_complete(h))) | 486 | else if( ( l = header_complete( h ) ) ) |
501 | httpresponse(clientsocket,h); | 487 | httpresponse( clientsocket, h); |
502 | } | 488 | } |
503 | 489 | ||
504 | void handle_write( int64 clientsocket ) { | 490 | void handle_write( int64 clientsocket ) { |
505 | struct http_data* h=io_getcookie(clientsocket); | 491 | struct http_data* h=io_getcookie( clientsocket ); |
506 | if( !h ) return; | 492 | if( !h ) return; |
507 | if( iob_send( clientsocket, &h->batch ) <= 0 ) { | 493 | if( iob_send( clientsocket, &h->batch ) <= 0 ) { |
508 | iob_reset( &h->batch ); | 494 | iob_reset( &h->batch ); |
@@ -525,7 +511,7 @@ void handle_accept( int64 serversocket ) { | |||
525 | while( ( i = socket_accept4( serversocket, (char*)ip, &port) ) != -1 ) { | 511 | while( ( i = socket_accept4( serversocket, (char*)ip, &port) ) != -1 ) { |
526 | 512 | ||
527 | if( !io_fd( i ) || | 513 | if( !io_fd( i ) || |
528 | !(h = (struct http_data*)malloc(sizeof(struct http_data))) ) { | 514 | !( h = (struct http_data*)malloc( sizeof struct http_data ) ) ) { |
529 | io_close( i ); | 515 | io_close( i ); |
530 | continue; | 516 | continue; |
531 | } | 517 | } |
@@ -557,9 +543,9 @@ void handle_accept( int64 serversocket ) { | |||
557 | void handle_timeouted( ) { | 543 | void handle_timeouted( ) { |
558 | int64 i; | 544 | int64 i; |
559 | while( ( i = io_timeouted() ) != -1 ) { | 545 | while( ( i = io_timeouted() ) != -1 ) { |
560 | struct http_data* h=io_getcookie(i); | 546 | struct http_data* h=io_getcookie( i ); |
561 | if( h ) { | 547 | if( h ) { |
562 | array_reset( &h->r ); | 548 | array_reset( &h->request ); |
563 | free( h ); | 549 | free( h ); |
564 | } | 550 | } |
565 | #ifdef _DEBUG_FDS | 551 | #ifdef _DEBUG_FDS |
@@ -576,28 +562,28 @@ void server_mainloop( int64 serversocket ) { | |||
576 | io_wantread( serversocket ); | 562 | io_wantread( serversocket ); |
577 | taia_now( &next_timeout_check ); | 563 | taia_now( &next_timeout_check ); |
578 | 564 | ||
579 | for (;;) { | 565 | for( ; ; ) { |
580 | int64 i; | 566 | int64 i; |
581 | 567 | ||
582 | taia_now(&t); | 568 | taia_now( &t ); |
583 | taia_addsec(&t,&t,OT_CLIENT_TIMEOUT_CHECKINTERVAL); | 569 | taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_CHECKINTERVAL ); |
584 | io_waituntil(t); | 570 | io_waituntil( t ); |
585 | 571 | ||
586 | while( ( i = io_canread() ) != -1 ) { | 572 | while( ( i = io_canread( ) ) != -1 ) { |
587 | if( i == serversocket ) | 573 | if( i == serversocket ) |
588 | handle_accept( i ); | 574 | handle_accept( i ); |
589 | else | 575 | else |
590 | handle_read( i ); | 576 | handle_read( i ); |
591 | } | 577 | } |
592 | 578 | ||
593 | while( ( i = io_canwrite() ) != -1 ) | 579 | while( ( i = io_canwrite( ) ) != -1 ) |
594 | handle_write( i ); | 580 | handle_write( i ); |
595 | 581 | ||
596 | taia_now(&t); | 582 | taia_now( &t ); |
597 | if( taia_less( &next_timeout_check, &t ) ) { | 583 | if( taia_less( &next_timeout_check, &t ) ) { |
598 | handle_timeouted( ); | 584 | handle_timeouted( ); |
599 | taia_now(&next_timeout_check); | 585 | taia_now( &next_timeout_check ); |
600 | taia_addsec(&next_timeout_check,&next_timeout_check,OT_CLIENT_TIMEOUT_CHECKINTERVAL); | 586 | taia_addsec( &next_timeout_check, &next_timeout_check, OT_CLIENT_TIMEOUT_CHECKINTERVAL); |
601 | } | 587 | } |
602 | } | 588 | } |
603 | } | 589 | } |
@@ -610,12 +596,12 @@ int main( int argc, char **argv ) { | |||
610 | int scanon = 1; | 596 | int scanon = 1; |
611 | 597 | ||
612 | while( scanon ) { | 598 | while( scanon ) { |
613 | switch( getopt(argc,argv,":i:p:d:ocbBh") ) { | 599 | switch( getopt( argc, argv, ":i:p:d:ocbBh" ) ) { |
614 | case -1 : scanon = 0; break; | 600 | case -1 : scanon = 0; break; |
615 | case 'i': serverip = optarg; break; | 601 | case 'i': serverip = optarg; break; |
616 | case 'p': port = (uint16)atol( optarg ); break; | 602 | case 'p': port = (uint16)atol( optarg ); break; |
617 | case 'd': serverdir = optarg; break; | 603 | case 'd': serverdir = optarg; break; |
618 | case 'h': help( argv[0]); exit(0); | 604 | case 'h': help( argv[0] ); exit( 0 ); |
619 | #ifdef WANT_CLOSED_TRACKER | 605 | #ifdef WANT_CLOSED_TRACKER |
620 | case 'o': g_closedtracker = 0; break; | 606 | case 'o': g_closedtracker = 0; break; |
621 | case 'c': g_closedtracker = 1; break; | 607 | case 'c': g_closedtracker = 1; break; |
@@ -625,21 +611,21 @@ int main( int argc, char **argv ) { | |||
625 | case 'B': g_check_blacklist = 0; break; | 611 | case 'B': g_check_blacklist = 0; break; |
626 | #endif | 612 | #endif |
627 | default: | 613 | default: |
628 | case '?': usage( argv[0] ); exit(1); | 614 | case '?': usage( argv[0] ); exit( 1 ); |
629 | } | 615 | } |
630 | } | 616 | } |
631 | 617 | ||
632 | if (socket_bind4_reuse(s,serverip,port)==-1) | 618 | if( socket_bind4_reuse( s, serverip, port ) == -1 ) |
633 | panic("socket_bind4_reuse"); | 619 | panic( "socket_bind4_reuse" ); |
634 | 620 | ||
635 | setegid((gid_t)-2); setuid((uid_t)-2); | 621 | setegid( (gid_t)-2 ); setuid( (uid_t)-2 ); |
636 | setgid((gid_t)-2); seteuid((uid_t)-2); | 622 | setgid( (gid_t)-2 ); seteuid( (uid_t)-2 ); |
637 | 623 | ||
638 | if (socket_listen(s,SOMAXCONN)==-1) | 624 | if( socket_listen( s, SOMAXCONN) == -1 ) |
639 | panic("socket_listen"); | 625 | panic( "socket_listen" ); |
640 | 626 | ||
641 | if (!io_fd(s)) | 627 | if( !io_fd( s ) ) |
642 | panic("io_fd"); | 628 | panic( "io_fd" ); |
643 | 629 | ||
644 | signal( SIGPIPE, SIG_IGN ); | 630 | signal( SIGPIPE, SIG_IGN ); |
645 | signal( SIGINT, graceful ); | 631 | signal( SIGINT, graceful ); |
@@ -647,11 +633,11 @@ int main( int argc, char **argv ) { | |||
647 | signal( SIGINFO, count_fds ); | 633 | signal( SIGINFO, count_fds ); |
648 | #endif | 634 | #endif |
649 | if( init_logic( serverdir ) == -1 ) | 635 | if( init_logic( serverdir ) == -1 ) |
650 | panic("Logic not started"); | 636 | panic( "Logic not started" ); |
651 | 637 | ||
652 | ot_start_time = time( NULL ); | 638 | ot_start_time = time( NULL ); |
653 | 639 | ||
654 | server_mainloop(s); | 640 | server_mainloop( s ); |
655 | 641 | ||
656 | return 0; | 642 | return 0; |
657 | } | 643 | } |