Mercurial > noffle
comparison src/client.c @ 180:09ca6eb5c7ff noffle
[svn] * TODO,src/client.c,src/client.h,src/fetch.c,src/fetch.h,src/noffle.c:
Improve error checking during fetches. A fetch is now aborted immediately
if the connection times out or if an unexpected response arrives.
This should fix problems with articles appearing in the wrong group,
and possibly other mysterious happenings.
author | bears |
---|---|
date | Wed, 09 May 2001 12:33:43 +0100 |
parents | 0ce333d046b9 |
children | a43a528cfbe7 |
comparison
equal
deleted
inserted
replaced
179:f973675760dc | 180:09ca6eb5c7ff |
---|---|
1 /* | 1 /* |
2 client.c | 2 client.c |
3 | 3 |
4 $Id: client.c 269 2001-03-13 11:46:03Z enz $ | 4 $Id: client.c 279 2001-05-09 11:33:43Z bears $ |
5 */ | 5 */ |
6 | 6 |
7 #if HAVE_CONFIG_H | 7 #if HAVE_CONFIG_H |
8 #include <config.h> | 8 #include <config.h> |
9 #endif | 9 #endif |
164 return putCmdLn( line ); | 164 return putCmdLn( line ); |
165 } | 165 } |
166 | 166 |
167 static int getStat( void ); | 167 static int getStat( void ); |
168 | 168 |
169 static Bool | 169 static int |
170 performAuth( void ) | 170 performAuth( void ) |
171 { | 171 { |
172 int stat; | 172 int stat; |
173 Str user, pass; | 173 Str user, pass; |
174 | 174 |
175 Cfg_authInfo( client.serv, user, pass ); | 175 Cfg_authInfo( client.serv, user, pass ); |
176 if ( strcmp( user, "" ) == 0 ) | 176 if ( strcmp( user, "" ) == 0 ) |
177 { | 177 { |
178 Log_err( "No username for authentication set" ); | 178 Log_err( "No username for authentication set" ); |
179 return FALSE; | 179 return STAT_AUTH_REQUIRED; |
180 } | 180 } |
181 putCmd( "AUTHINFO USER %s", user ); | 181 putCmd( "AUTHINFO USER %s", user ); |
182 stat = getStat(); | 182 stat = getStat(); |
183 if ( stat == STAT_AUTH_ACCEPTED ) | 183 if ( stat == STAT_AUTH_ACCEPTED ) |
184 return TRUE; | 184 return stat; |
185 else if ( stat != STAT_MORE_AUTH_REQUIRED ) | 185 else if ( stat != STAT_MORE_AUTH_REQUIRED ) |
186 { | 186 { |
187 Log_err( "Username rejected. Server stat: %s", client.lastStat ); | 187 Log_err( "Username rejected. Server stat: %s", client.lastStat ); |
188 return FALSE; | 188 return stat; |
189 } | 189 } |
190 if ( strcmp( pass, "" ) == 0 ) | 190 if ( strcmp( pass, "" ) == 0 ) |
191 { | 191 { |
192 Log_err( "No password for authentication set" ); | 192 Log_err( "No password for authentication set" ); |
193 return FALSE; | 193 return STAT_AUTH_REQUIRED; |
194 } | 194 } |
195 putCmd( "AUTHINFO PASS %s", pass ); | 195 putCmd( "AUTHINFO PASS %s", pass ); |
196 stat = getStat(); | 196 stat = getStat(); |
197 if ( stat != STAT_AUTH_ACCEPTED ) | 197 if ( stat != STAT_AUTH_ACCEPTED ) |
198 { | |
199 Log_err( "Password rejected. Server status: %s", client.lastStat ); | 198 Log_err( "Password rejected. Server status: %s", client.lastStat ); |
200 return FALSE; | 199 return stat; |
201 } | |
202 return TRUE; | |
203 } | 200 } |
204 | 201 |
205 static int | 202 static int |
206 getStat( void ) | 203 getStat( void ) |
207 { | 204 { |
217 } | 214 } |
218 if ( result == STAT_AUTH_REQUIRED && ! client.auth ) | 215 if ( result == STAT_AUTH_REQUIRED && ! client.auth ) |
219 { | 216 { |
220 client.auth = TRUE; | 217 client.auth = TRUE; |
221 strcpy( lastCmd, client.lastCmd ); | 218 strcpy( lastCmd, client.lastCmd ); |
222 if ( performAuth() ) | 219 result = performAuth(); |
220 if ( result == STAT_AUTH_ACCEPTED ) | |
223 { | 221 { |
224 putCmd( lastCmd ); | 222 putCmd( lastCmd ); |
225 return getStat(); | 223 return getStat(); |
226 } | 224 } |
227 } | 225 } |
531 | 529 |
532 *noServerPattern = FALSE; | 530 *noServerPattern = FALSE; |
533 if ( ! putCmd( cmd ) ) | 531 if ( ! putCmd( cmd ) ) |
534 return FALSE; | 532 return FALSE; |
535 stat = getStat(); | 533 stat = getStat(); |
534 if ( stat == STAT_PROGRAM_FAULT ) | |
535 return FALSE; | |
536 | |
537 /* | |
538 * Try LIST instead of LIST ACTIVE in case server doesn't | |
539 * support LIST ACTIVE. | |
540 */ | |
536 if ( pattern[ 0 ] != '\0' && stat != STAT_GRPS_FOLLOW ) | 541 if ( pattern[ 0 ] != '\0' && stat != STAT_GRPS_FOLLOW ) |
537 { | 542 { |
538 *noServerPattern = TRUE; | 543 *noServerPattern = TRUE; |
539 if ( ! putCmd( "LIST" ) ) | 544 if ( ! putCmd( "LIST" ) ) |
540 return FALSE; | 545 return FALSE; |
587 { | 592 { |
588 Str name, line, dsc, cmd; | 593 Str name, line, dsc, cmd; |
589 int stat; | 594 int stat; |
590 DynStr *response; | 595 DynStr *response; |
591 const char *lines; | 596 const char *lines; |
597 Bool result; | |
592 | 598 |
593 ASSERT( ! Lock_gotLock() ); | 599 ASSERT( ! Lock_gotLock() ); |
594 Utl_cpyStr( cmd, "LIST NEWSGROUPS" ); | 600 Utl_cpyStr( cmd, "LIST NEWSGROUPS" ); |
595 if ( pattern[ 0 ] != '\0' ) | 601 if ( pattern[ 0 ] != '\0' ) |
596 { | 602 { |
600 | 606 |
601 *noServerPattern = FALSE; | 607 *noServerPattern = FALSE; |
602 if ( ! putCmd( cmd ) ) | 608 if ( ! putCmd( cmd ) ) |
603 return FALSE; | 609 return FALSE; |
604 stat = getStat(); | 610 stat = getStat(); |
611 if ( stat == STAT_PROGRAM_FAULT ) | |
612 return FALSE; | |
613 | |
614 /* Try without pattern in case server doesn't support patterns. */ | |
605 if ( pattern[ 0 ] != '\0' && stat != STAT_GRPS_FOLLOW ) | 615 if ( pattern[ 0 ] != '\0' && stat != STAT_GRPS_FOLLOW ) |
606 { | 616 { |
607 *noServerPattern = TRUE; | 617 *noServerPattern = TRUE; |
608 if ( !putCmd( "LIST NEWSGROUPS" ) ) | 618 if ( !putCmd( "LIST NEWSGROUPS" ) ) |
609 return FALSE; | 619 return FALSE; |
621 | 631 |
622 if ( ! Lock_openDatabases() ) | 632 if ( ! Lock_openDatabases() ) |
623 return FALSE; | 633 return FALSE; |
624 | 634 |
625 lines = DynStr_str( response ); | 635 lines = DynStr_str( response ); |
636 result = TRUE; | |
626 while ( ( lines = Utl_getLn( line, lines) ) != NULL ) | 637 while ( ( lines = Utl_getLn( line, lines) ) != NULL ) |
627 { | 638 { |
628 if ( sscanf( line, "%s", name ) != 1 ) | 639 if ( sscanf( line, "%s", name ) != 1 ) |
629 { | 640 { |
630 Log_err( "Unknown reply to LIST NEWSGROUPS: %s", line ); | 641 Log_err( "Unknown reply to LIST NEWSGROUPS: %s", line ); |
631 continue; | 642 result = FALSE; |
643 break; | |
632 } | 644 } |
633 if ( *noServerPattern && ! isGetGroup( name ) ) | 645 if ( *noServerPattern && ! isGetGroup( name ) ) |
634 continue; | 646 continue; |
635 strcpy( dsc, Utl_restOfLn( line, 1 ) ); | 647 strcpy( dsc, Utl_restOfLn( line, 1 ) ); |
636 if ( Grp_exists( name ) ) | 648 if ( Grp_exists( name ) ) |
639 Grp_setDsc( name, dsc ); | 651 Grp_setDsc( name, dsc ); |
640 } | 652 } |
641 } | 653 } |
642 Lock_closeDatabases(); | 654 Lock_closeDatabases(); |
643 del_DynStr( response ); | 655 del_DynStr( response ); |
644 return TRUE; | 656 return result; |
645 } | 657 } |
646 | 658 |
647 Bool | 659 Bool |
648 Client_getDsc( void ) | 660 Client_getDsc( void ) |
649 { | 661 { |
662 doneOne = TRUE; | 674 doneOne = TRUE; |
663 if ( noServerPattern ) | 675 if ( noServerPattern ) |
664 break; | 676 break; |
665 } | 677 } |
666 | 678 |
667 if ( ! doneOne ) | 679 if ( res && ! doneOne ) |
668 res = doGetDsc( "", &noServerPattern ); | 680 res = doGetDsc( "", &noServerPattern ); |
669 | 681 |
670 del_GrEn( ge ); | 682 del_GrEn( ge ); |
671 return res; | 683 return res; |
672 } | 684 } |
907 | 919 |
908 Log_dbg( "Requesting Newsgroups headers for remote %lu-%lu", | 920 Log_dbg( "Requesting Newsgroups headers for remote %lu-%lu", |
909 rmtFirst, rmtLast ); | 921 rmtFirst, rmtLast ); |
910 | 922 |
911 newsgroups = collectTxt(); | 923 newsgroups = collectTxt(); |
924 if ( newsgroups == NULL ) | |
925 return FALSE; | |
926 | |
912 groupLines = DynStr_str( newsgroups ); | 927 groupLines = DynStr_str( newsgroups ); |
913 } | 928 } |
914 else | 929 else |
915 { | 930 { |
916 groupLines = NULL; | 931 groupLines = NULL; |
1061 else | 1076 else |
1062 retrievingFailed( msgId, "Connection broke down" ); | 1077 retrievingFailed( msgId, "Connection broke down" ); |
1063 return ! err; | 1078 return ! err; |
1064 } | 1079 } |
1065 | 1080 |
1066 void | 1081 Bool |
1067 Client_retrieveArt( const char *msgId ) | 1082 Client_retrieveArt( const char *msgId ) |
1068 { | 1083 { |
1084 Bool res = FALSE; | |
1085 | |
1069 ASSERT( Lock_gotLock() ); | 1086 ASSERT( Lock_gotLock() ); |
1070 if ( ! Db_contains( msgId ) ) | 1087 if ( ! Db_contains( msgId ) ) |
1071 { | 1088 { |
1072 Log_err( "Article '%s' not prepared in database. Skipping.", msgId ); | 1089 Log_err( "Article '%s' not prepared in database. Skipping.", msgId ); |
1073 return; | 1090 return TRUE; |
1074 } | 1091 } |
1075 if ( ! ( Db_status( msgId ) & DB_NOT_DOWNLOADED ) ) | 1092 if ( ! ( Db_status( msgId ) & DB_NOT_DOWNLOADED ) ) |
1076 { | 1093 { |
1077 Log_inf( "Article '%s' already retrieved. Skipping.", msgId ); | 1094 Log_inf( "Article '%s' already retrieved. Skipping.", msgId ); |
1078 return; | 1095 return TRUE; |
1079 } | 1096 } |
1080 | 1097 |
1081 Lock_closeDatabases(); | 1098 Lock_closeDatabases(); |
1082 if ( ! putCmd( "ARTICLE %s", msgId ) ) | 1099 if ( ! putCmd( "ARTICLE %s", msgId ) ) |
1083 retrievingFailed( msgId, "Connection broke down" ); | 1100 retrievingFailed( msgId, "Connection broke down" ); |
1084 else if ( getStat() != STAT_ART_FOLLOWS ) | 1101 else if ( getStat() != STAT_ART_FOLLOWS ) |
1085 retrievingFailed( msgId, client.lastStat ); | 1102 retrievingFailed( msgId, client.lastStat ); |
1086 else | 1103 else |
1087 retrieveAndStoreArt( msgId, 0, 0 ); | 1104 res = retrieveAndStoreArt( msgId, 0, 0 ); |
1088 Lock_openDatabases(); | 1105 Lock_openDatabases(); |
1089 } | 1106 return res; |
1090 | 1107 } |
1091 void | 1108 |
1109 Bool | |
1092 Client_retrieveArtList( const char *list, int *artcnt, int artmax ) | 1110 Client_retrieveArtList( const char *list, int *artcnt, int artmax ) |
1093 { | 1111 { |
1094 Str msgId; | 1112 Str msgId; |
1095 DynStr *s; | 1113 DynStr *s; |
1096 const char *p; | 1114 const char *p; |
1115 Bool res; | |
1097 | 1116 |
1098 ASSERT( Lock_gotLock() ); | 1117 ASSERT( Lock_gotLock() ); |
1099 Log_inf( "Retrieving article list" ); | 1118 Log_inf( "Retrieving article list" ); |
1100 s = new_DynStr( (int)strlen( list ) ); | 1119 s = new_DynStr( (int)strlen( list ) ); |
1101 p = list; | 1120 p = list; |
1107 Log_inf( "[%d/%d] Skipping %s (already retrieved)", ++(*artcnt), artmax, msgId ); | 1126 Log_inf( "[%d/%d] Skipping %s (already retrieved)", ++(*artcnt), artmax, msgId ); |
1108 else if ( ! putCmdNoFlush( "ARTICLE %s", msgId ) ) | 1127 else if ( ! putCmdNoFlush( "ARTICLE %s", msgId ) ) |
1109 { | 1128 { |
1110 retrievingFailed( msgId, "Connection broke down" ); | 1129 retrievingFailed( msgId, "Connection broke down" ); |
1111 del_DynStr( s ); | 1130 del_DynStr( s ); |
1112 return; | 1131 return FALSE; |
1113 } | 1132 } |
1114 else | 1133 else |
1115 DynStr_appLn( s, msgId ); | 1134 DynStr_appLn( s, msgId ); |
1116 | 1135 |
1117 Lock_closeDatabases(); | 1136 Lock_closeDatabases(); |
1118 fflush( client.out ); | 1137 fflush( client.out ); |
1119 Log_dbg( "[S FLUSH]" ); | 1138 Log_dbg( "[S FLUSH]" ); |
1120 | 1139 |
1121 p = DynStr_str( s ); | 1140 p = DynStr_str( s ); |
1122 while ( ( p = Utl_getLn( msgId, p ) ) ) | 1141 res = TRUE; |
1142 while ( res && ( p = Utl_getLn( msgId, p ) ) ) | |
1123 { | 1143 { |
1124 if ( getStat() != STAT_ART_FOLLOWS ) | 1144 if ( getStat() != STAT_ART_FOLLOWS ) |
1145 { | |
1125 retrievingFailed( msgId, client.lastStat ); | 1146 retrievingFailed( msgId, client.lastStat ); |
1126 else if ( ! retrieveAndStoreArt( msgId, ++(*artcnt), artmax ) ) | 1147 res = FALSE; |
1127 break; | 1148 } |
1149 else | |
1150 res = retrieveAndStoreArt( msgId, ++(*artcnt), artmax ); | |
1128 } | 1151 } |
1129 del_DynStr( s ); | 1152 del_DynStr( s ); |
1130 Lock_openDatabases(); | 1153 Lock_openDatabases(); |
1154 return res; | |
1131 } | 1155 } |
1132 | 1156 |
1133 Bool | 1157 Bool |
1134 Client_changeToGrp( const char* name ) | 1158 Client_changeToGrp( const char* name ) |
1135 { | 1159 { |
1164 *first = client.rmtFirst; | 1188 *first = client.rmtFirst; |
1165 *last = client.rmtLast; | 1189 *last = client.rmtLast; |
1166 } | 1190 } |
1167 | 1191 |
1168 Bool | 1192 Bool |
1169 Client_postArt( const char *msgId, const char *artTxt, | 1193 Client_postArt( const char *msgId, const char *artTxt, Str errStr ) |
1170 Str errStr ) | 1194 { |
1171 { | 1195 int stat; |
1196 | |
1197 errStr[0] = '\0'; | |
1198 | |
1172 if ( ! putCmd( "POST" ) ) | 1199 if ( ! putCmd( "POST" ) ) |
1173 return FALSE; | 1200 return FALSE; |
1174 if ( getStat() != STAT_SEND_ART ) | 1201 stat = getStat(); |
1202 if ( stat == STAT_PROGRAM_FAULT ) | |
1203 return FALSE; | |
1204 else if ( stat != STAT_SEND_ART ) | |
1175 { | 1205 { |
1176 Log_err( "Posting of %s not allowed: %s", msgId, client.lastStat ); | 1206 Log_err( "Posting of %s not allowed: %s", msgId, client.lastStat ); |
1177 strcpy( errStr, client.lastStat ); | 1207 strcpy( errStr, client.lastStat ); |
1178 return FALSE; | 1208 return TRUE; |
1179 } | 1209 } |
1180 putTxtBuf( artTxt ); | 1210 putTxtBuf( artTxt ); |
1181 putEndOfTxt(); | 1211 putEndOfTxt(); |
1182 if ( getStat() != STAT_POST_OK ) | 1212 stat = getStat(); |
1213 if ( stat == STAT_PROGRAM_FAULT ) | |
1214 return FALSE; | |
1215 else if ( stat != STAT_POST_OK ) | |
1183 { | 1216 { |
1184 Log_err( "Posting of %s failed: %s", msgId, client.lastStat ); | 1217 Log_err( "Posting of %s failed: %s", msgId, client.lastStat ); |
1185 strcpy( errStr, client.lastStat ); | 1218 strcpy( errStr, client.lastStat ); |
1186 return FALSE; | 1219 return TRUE; |
1187 } | 1220 } |
1188 Log_inf( "Posted %s (Status: %s)", msgId, client.lastStat ); | 1221 Log_inf( "Posted %s (Status: %s)", msgId, client.lastStat ); |
1189 return TRUE; | 1222 return TRUE; |
1190 } | 1223 } |