/* Procedure to transmit a string to the remot peer*/
/* */
/********************************************************/
-static void transmit(CONTYP *contact,const char *fmt,...)
+static void transmit(CONTYP *contact,_Bool flush,const char *fmt,...)
{
va_list args;
line=(char *)0;
if (rou_vasprintf(&line,fmt,args)>0) {
(void) log_fprintlog(contact->logptr,true,"%s",line);
- (void) tcp_write(contact->socptr,line);
- (void) free(line);
+ contact->transout=tcp_addline(contact->transout,line);
}
+if (flush==true) {
+ (void) tcp_write(contact->socptr,contact->transout);
+ contact->transout=rou_freestr(contact->transout);
+ }
+line=rou_freestr(line);
va_end(args);
}
/*
APPNAME,
rou_getversion(),
rou_ascsysstamp(time((time_t *)0)));
- (void) transmit(contact,"%s",signon);
+ (void) transmit(contact,true,"%s",signon);
}
#undef FMT
}
if (suite==true)
sepa='-';
mode=soc_getstrmode(contact->socptr);
-(void) transmit(contact,"%d%c%s, link (%s) ready, your IP/FQDN=[%s/%s]",
- CMDOK,sepa,contact->locname,mode,
- contact->peerip,contact->peername);
+(void) transmit(contact,true,"%d%c%s, link (%s) ready, your IP/FQDN=[%s/%s]",
+ CMDOK,sepa,contact->locname,mode,
+ contact->peerip,contact->peername);
}
/*
^L
char *cmt;
cmt="RCPT first. transaction protocol command out of sequence";
- (void) transmit(contact,"%d 5.5.0 %s",BADSEQ,cmt);
+ (void) transmit(contact,true,"%d 5.5.0 %s",BADSEQ,cmt);
done=true; //lets say DATA will be issued
proceed=false; //No recipients
}
break;
case 3 : //sending 'go ahead' to remote
(void) clock_gettime(CLOCK_REALTIME,&start);
- (void) transmit(contact,"%d 3.5.0 %s",
+ (void) transmit(contact,true,"%d 3.5.0 %s",
DATAOK,"End data with <CR><LF>.<CR><LF>");
break;
case 4 : //get incoming line, detect 'single dot' as end
total/=1024; //KBytes
delta=rou_getdifftime(&start);
fmt="%d 3.5.3 Message accepted for delivery (Session ID=<%s>)";
- (void) transmit(contact,fmt,CMDOK,contact->cursesid);
+ (void) transmit(contact,true,fmt,CMDOK,contact->cursesid);
fmt="(DATA stream received: %d Kbytes within %d.%03d seconds)";
(void) log_fprintlog(contact->logptr,false,fmt,total,delta/1000,delta%1000);
done=true;
proceed=false; //task done
break;
default : //SAFE guard
- (void) transmit(contact,"%d 5.5.4 %s",
- DATRJC,"Server does not accept mail");
+ (void) transmit(contact,true,"%d 5.5.4 %s",
+ DATRJC,"Server does not accept mail");
proceed=false;
break;
}
_Bool done;
if ((done=isgoodfqdn(contact,parameter))==false)
- (void) transmit(contact,"%d 5.5.4 %s.",BADPAR,DETAIL);
+ (void) transmit(contact,true,"%d 5.5.4 %s.",BADPAR,DETAIL);
else
(void) linkready(contact,false);
return done;
switch (phase) {
case 0 : //Do we have a parameter
if ((done=isgoodfqdn(contact,parameter))==false) {
- (void) transmit(contact,"%d 5.5.4 %s.",BADPAR,DETAIL);
+ (void) transmit(contact,true,"%d 5.5.4 %s.",BADPAR,DETAIL);
phase=999; //Trouble trouble
}
break;
case 1 : //thereis an FQDN
(void) linkready(contact,true);
- (void) transmit(contact,"%d-SIZE %ld",CMDOK,MXMSIZE);
+ (void) transmit(contact,false,"%d-SIZE %ld",CMDOK,MXMSIZE);
if (soc_iscrypted(contact->socptr)==true)
strstart++;
for (int i=strstart;ehlostr[i]!=(char *)0;i++) {
- (void) transmit(contact,"%d%s",CMDOK,ehlostr[i]);
+ (void) transmit(contact,false,"%d%s",CMDOK,ehlostr[i]);
}
+ (void) transmit(contact,true,"");
done=true;
break;
default : //SAFE guard
switch (phase) {
case 0 : //do we have an originator
if ((mailfrom==(char *)0)||(strlen(mailfrom)<3)) {
- (void) transmit(contact,"%d 5.5.0 <%s> originator not specified",
- BADPAR,mailfrom);
+ (void) transmit(contact,true,"%d 5.5.0 <%s> originator not specified",
+ BADPAR,mailfrom);
phase=999; //no need to go further
}
break;
case 1 : //do we have already a from
if (contact->mailfrom!=(char *)0) {
- (void) transmit(contact,"%d 5.5.1 '%s' %s",
- BADPAR,contact->mailfrom,
- "was previously defined as originator"
- );
+ (void) transmit(contact,true,"%d 5.5.1 '%s' %s",
+ BADPAR,contact->mailfrom,
+ "was previously defined as originator");
phase=999; //no need to go further
}
break;
case 2 : //check from format
if ((mailfrom[0]!='<')||(mailfrom[strlen(mailfrom)-1]!='>')) {
- (void) transmit(contact,"%d 5.5.2 '%s' bad Format error",
- BADPAR,mailfrom);
+ (void) transmit(contact,true,"%d 5.5.2 '%s' bad Format error",
+ BADPAR,mailfrom);
phase=999; //no need to go further
}
mailfrom[strlen(mailfrom)-1]='\000';
break;
case 3 : //everything ok
contact->mailfrom=strdup(mailfrom);
- (void) transmit(contact,"%d 2.1.3 %s.. sender ok",
- CMDOK,contact->mailfrom);
+ (void) transmit(contact,true,"%d 2.1.3 %s.. sender ok",
+ CMDOK,contact->mailfrom);
break;
default : //SAFE guard
proceed=false;
switch (phase) {
case 0 : //do we have a mailfrom
if ((contact->mailfrom==(char *)0)||(strlen(contact->mailfrom)==0)) {
- (void) transmit(contact,"%d Bad sequence of commands.",BADSEQ);
+ (void) transmit(contact,true,"%d Bad sequence of commands.",BADSEQ);
phase=999; //no need to go further
}
break;
case 1 : //do we have an originator
if ((rcptto==(char *)0)||(strlen(rcptto)==0)) {
- (void) transmit(contact,"%d 5.6.0 recipient not specified",BADPAR);
+ (void) transmit(contact,true,"%d 5.6.0 recipient not specified",BADPAR);
phase=999; //no need to go further
}
break;
case 2 : //check rcpt format
if ((rcptto[0]!='<')||(rcptto[strlen(rcptto)-1]!='>')) {
- (void) transmit(contact,"%d 5.6.1 '%s' bad Format error",
- BADPAR,rcptto);
+ (void) transmit(contact,true,"%d 5.6.1 '%s' bad Format error",
+ BADPAR,rcptto);
phase=999; //no need to go further
}
rcptto[strlen(rcptto)-1]='\000';
case 3 : //checking rcptto format
neu=eml_isemailok(rcptto,&report);
if (neu==(RCPTYP *)0) {
- (void) transmit(contact,"%d 5.6.2 %s",NOTEML,report);
+ (void) transmit(contact,true,"%d 5.6.2 %s",NOTEML,report);
report=rou_freestr(report);
phase=999; //no need to go further
}
break;
case 4 : //Do we have a domain MX
if (setlocdom(contact,neu)==false) {
- (void) transmit(contact,"%d 5.6.3 %s (domain=%s)",
- MISSMX,
- "No valid MX found for recipient domain name",
- neu->domain);
+ (void) transmit(contact,true,"%d 5.6.3 %s (domain=%s)",
+ MISSMX,
+ "No valid MX found for recipient domain name",
+ neu->domain);
neu=eml_freerecipient(neu); //free recipient
phase=999; //no need to go further
}
}
break;
case 6 : //everything ok
- (void) transmit(contact,"%d 2.6.4 %s <%s>",CMDOK,detail,rcptto);
+ (void) transmit(contact,true,"%d 2.6.4 %s <%s>",CMDOK,detail,rcptto);
success=true;
break;
default : //SAFE guard
{
#define LOCSEQ "2.1.0"
-(void) transmit(contact,"%d-%s flushed session %s",
- CMDOK,LOCSEQ,contact->cursesid);
+(void) transmit(contact,true,"%d-%s flushed session %s",
+ CMDOK,LOCSEQ,contact->cursesid);
contact->numreset++;
contact->recipients=(RCPTYP **)rou_freelist((void **)(contact->recipients),
(genfree_t)eml_freerecipient);
contact->mailfrom=rou_freestr(contact->mailfrom);
contact->cursesid=rou_freestr(contact->cursesid);
contact->cursesid=eml_getcursesid(contact->mainsesid,contact->numreset);
-(void) transmit(contact,"%d %s opening new session %s",
- CMDOK,LOCSEQ,contact->cursesid);
+(void) transmit(contact,true,"%d %s opening new session %s",
+ CMDOK,LOCSEQ,contact->cursesid);
return true;
#undef LOCSEQ
proceed=doehlo(contact,line);
break;
case c_noop : //No Operation
- (void) transmit(contact,"%d 2.0.0 OK, %s",
- CMDOK,contact->mainsesid);
+ (void) transmit(contact,true,"%d 2.0.0 OK, %s",
+ CMDOK,contact->mainsesid);
break;
case c_quit : //QUIT SMTP protocol
- (void) transmit(contact,"%d 2.0.0 Bye, closing connection CNT=%s",
- QUITOK,contact->mainsesid);
+ (void) transmit(contact,true,"%d 2.0.0 Bye, closing connection CNT=%s",
+ QUITOK,contact->mainsesid);
status=1; //every thing fine
proceed=false;
break;
case c_starttls : //EHLO start encrypted link in server mode
switch (soc_starttls(contact->socptr,true)) {
case true : //link now in TLS crypted mode
+ char *loc;
+
+ loc=strdup(contact->fqdn);
+ //(void) doehlo(contact,loc);
+ loc=rou_freestr(loc);
/* JMPDBG
(void) transmit(contact,"%d Link now encrypted (cipher=<%s>)",
CMDOK,soc_get_cipher_name(contact->socptr));
*/
break;
case false : //unable to establish link
- (void) transmit(contact,"%d 5.3.3 command starttls not successful",
- CMDBAD);
+ (void) transmit(contact,true,"%d 5.3.3 command starttls not successful",
+ CMDBAD);
status=-1;
proceed=false;
break;
case c_unknown : //unknown keyword
(void) rou_alert(0,"SMTP Command <%s> from [%s] is unknown (config?)",
line,contact->peerip);
- (void) transmit(contact,"%d-5.5.1 Unrecognized command, see RFC 5321",CMDBAD);
- (void) transmit(contact,"%d-5.5.1 https://www.rfc-editor.org",CMDBAD);
- (void) transmit(contact,"%d 5.5.1 session %s is still running",
- CMDBAD,contact->mainsesid);
+ (void) transmit(contact,true,"%d-5.5.1 Unrecognized command, see RFC 5321",
+ CMDBAD);
+ (void) transmit(contact,true,"%d-5.5.1 https://www.rfc-editor.org",CMDBAD);
+ (void) transmit(contact,true,"%d 5.5.1 session %s is still running",
+ CMDBAD,contact->mainsesid);
break;
default :
(void) rou_alert(0,"%s Unable to find entry for code='%d' (Bug?)",OPEP,code);
- (void) transmit(contact,"%d-5.5.1 Unrecognized command, see RFC 5321",CMDBAD);
- (void) transmit(contact,"%d 2.0.0 Bug!, closing connection Immediatly (%s)",
- QUITOK,contact->mainsesid);
+ (void) transmit(contact,true,"%d-5.5.1 Unrecognized command, see RFC 5321",
+ CMDBAD);
+ (void) transmit(contact,true,"%d 2.0.0 Bug!, closing connection "
+ "Immediatly (%s)",
+ QUITOK,contact->mainsesid);
status=-1; //remote is a trouble maker
status=-3;
proceed=false;