TCP.Mod 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE TCP; (** AUTHOR "pjm, mvt"; PURPOSE "TCP protocol"; *)
  3. (*
  4. TCP - Transmission Control Protocol. Based on the 4.4BSD-Lite distribution described in Wright and Stevens, "TCP/IP Illustrated, Volume 2: The Implementation", ISBN 0-201-63354-X. See the BSD copyright statement at the end of this module. From that code it inherits some horrible control flow, which was left mostly intact, to make it easier to compare with the book.
  5. TCP Header
  6. 00 16 source port
  7. 02 16 destination port
  8. 04 32 sequence number
  9. 08 32 acknowledgement number
  10. 12 08 header length & reserved
  11. 07..04 header length (4-byte units)
  12. 03..00 reserved
  13. 13 08 flags
  14. 07..06 reserved
  15. 05..05 URG
  16. 04..04 ACK
  17. 03..03 PSH
  18. 02..02 RST
  19. 01..01 SYN
  20. 00..00 FIN
  21. 14 16 window size
  22. 16 16 TCP checksum
  23. 18 16 urgent pointer
  24. 20 -- options (0-40 bytes)
  25. -- -- data
  26. TCP Pseudo-header (for checksum calculation)
  27. 00 32 source address
  28. 04 32 destination address
  29. 08 08 zero = 0
  30. 09 08 protocol = 17
  31. 10 16 TCP length (duplicate)
  32. Notes:
  33. o Bit numbers above are Intel bit order.
  34. o Avoid use of SET because of PPC bit numbering issues.
  35. o Always access fields as 8-, 16- or 32-bit values and use DIV, MOD, ASH, ODD for bit access.
  36. *)
  37. IMPORT SYSTEM, Machine, KernelLog, Clock, Modules, Objects, Kernel, Commands, Network, IP, Streams, ActiveTimers;
  38. CONST
  39. StrongChecks = FALSE;
  40. SystemMove = FALSE;
  41. TraceProtocol = FALSE;
  42. TraceError = FALSE;
  43. TracePacket = FALSE;
  44. TraceTimer = FALSE;
  45. TraceCongestion = FALSE;
  46. Trace = TraceProtocol OR TraceError OR TracePacket OR TraceTimer;
  47. HandleCongestion = TRUE;
  48. MinEphemeralPort = 1024;
  49. MaxEphemeralPort = 50000;
  50. HashTableSize = 1024 * 16; (* size of connection lookup hash table *)
  51. Acceptable = 500; (* "backlog" on listening connections *)
  52. NilPort* = 0;
  53. (** Error codes *)
  54. Ok* = 0;
  55. ConnectionRefused* = 3701;
  56. ConnectionReset* = 3702;
  57. WrongInterface* = 3703;
  58. TimedOut* = 3704;
  59. NotConnected* = 3705;
  60. NoInterface* = 3706;
  61. InterfaceClosed* = 3707;
  62. MinError = 3700;
  63. MaxError = 3735;
  64. NumErrors = MaxError-MinError+1;
  65. (** TCP connection states *)
  66. NumStates* = 12;
  67. Closed* = 0;
  68. Listen* = 1;
  69. SynSent* = 2;
  70. SynReceived* = 3;
  71. Established* = 4;
  72. CloseWait* = 5;
  73. FinWait1* = 6;
  74. Closing* = 7;
  75. LastAck* = 8;
  76. FinWait2* = 9;
  77. TimeWait* = 10;
  78. Unused* = 11; (* no real state, only used in this implementation *)
  79. OpenStates* = {Listen, SynReceived, Established, CloseWait, FinWait1, FinWait2};
  80. ClosedStates* = {Unused, Closed, Closing, LastAck, TimeWait};
  81. HalfClosedStates* = ClosedStates + {FinWait1, FinWait2};
  82. FinStates* = {Unused, Closed, CloseWait, Closing, LastAck, TimeWait};
  83. Fin = 0; Syn = 1; Rst = 2; Psh = 3; Ack = 4; Urg = 5; (* tcp header flags *)
  84. DoRFC1323 = TRUE; (* handle time stamp option (processing and generating) *)
  85. ProcOptions = TRUE; (* process TCP options *)
  86. GenOptions = TRUE; (* generate TCP options *)
  87. (* Flags in Connection *)
  88. AckNow = 0; (* send Ack immediately *)
  89. DelAck = 1; (* send Ack, but try to delay it *)
  90. NoDelay = 2; (* don't delay packets tocoalesce (disable Nagle algorithm) *)
  91. SentFin = 3; (* have sent Fin *)
  92. Force = 4; (* force out a byte (persist/OOB) *)
  93. RcvdScale = 5; (* set when other side sends window scale option in Syn *)
  94. RcvdTstmp = 6; (* set when other side sends timestamp option in Syn *)
  95. ReqScale = 7; (* have/will request window scale option in Syn *)
  96. ReqTstmp = 8; (* have/will request timestamp option in Syn *)
  97. DoKeepAlive = 9; (* enable keep-alive timer *)
  98. AcceptConn = 10; (* listening for incoming connections *)
  99. (*Notify = 11;*) (* socket wakeup *)
  100. (*Gone = 12;*) (* SS_NOFDREF *)
  101. (*NoMore = 13;*) (* SS_CANTRCVMORE *)
  102. Timeout = 14;
  103. NumTimers = 4;
  104. ReXmt = 0; Persist = 1; Keep = 2; MSL2 = 3;
  105. FastPeriod = 5; (* number of fast ticks per second *)
  106. SlowPeriod = 2; (* number of slow ticks per second *)
  107. TimerPeriod = 10; (* timer ticks per second *)
  108. MinTime = 1*SlowPeriod; (* minimum allowable time value *)
  109. ReXmtMax = 64*SlowPeriod; (* max allowable ReXmt value *)
  110. ReXmtThresh = 3;
  111. KeepInit = 75*SlowPeriod; (* connection establishment timer value (75s) *)
  112. KeepIntvl = 75*SlowPeriod; (* time between probes when no response (75s) *)
  113. KeepIdle = 2*60*60*SlowPeriod; (* default time before probing (2h) *)
  114. KeepCnt = 8; (* max probes before drop *)
  115. MaxIdle = KeepCnt * KeepIntvl; (* max time to send keepalive probes (10min) *)
  116. MSL = 30*SlowPeriod; (* max segment lifetime (30s) *)
  117. MaxPersistIdle = KeepIdle; (* max time to keep dead/unreachable connections (2h) *)
  118. PawsIdle = 24*24*60*60*SlowPeriod;
  119. SRTTBase = 0; (* base round trip time *)
  120. SRTTDflt = 3*SlowPeriod; (* assumed RTT if no info *)
  121. RTTShift = 3;
  122. RTTVarShift = 2;
  123. PersMin = 5*SlowPeriod; (* retransmit persistance *)
  124. PersMax = 60*SlowPeriod; (* maximum persist interval *)
  125. MSS = 536-12; (* maximum segment size for outgoing segments, 12 = size of timestamp option *)
  126. MaxRxtShift = 12; (* maximum retransmits *)
  127. MaxWin = 65535; (* largest value for (unscaled) window *)
  128. MaxWinShift = 14; (* maximum window shift *)
  129. MaxSendSpace = 80000H; (* 512KB, max. 1023MB *)
  130. MaxRecvSpace = 80000H; (* 512KB, max. 1023MB *)
  131. SegsPerBuf = 4; (* number of mss segments per send buffer (potential fragmentation waste is 1/SegsPerBuf) *)
  132. ISSInc = 128000; (* increment for iss each second *)
  133. IPTypeTCP = 6; (* TCP type code for IP packets *)
  134. MinTCPHdrLen = 20;
  135. MaxTCPHdrLen = 60;
  136. MaxPseudoHdrLen = 40; (* IPv4 = 12; IPv6 = 40 *)
  137. NewZeros = FALSE; (* NEW initializes allocated object fields to 0 *)
  138. BroadcastReceived = 3708;
  139. InvalidParameter = 3709;
  140. AllPortsInUse = 3710;
  141. AddressInUse = 3711;
  142. DuplicateSegment = 3712;
  143. DuplicatePartialSegment = 3713;
  144. DuplicateSegmentPAWS = 3714;
  145. DataBeyondWindow1 = 3715;
  146. DataBeyondWindow2 = 3716;
  147. DataBeyondWindow3 = 3717;
  148. BadChecksum = 3718;
  149. DuplicateAck = 3719;
  150. OutOfRangeAck = 3720;
  151. TimeOutKeepAlive = 3721;
  152. TimeoutEstablished = 3722;
  153. SegmentTooBig = 3723;
  154. SegmentTooSmall = 3724;
  155. BadHeaderLength = 3725;
  156. ConnectionGone = 3726;
  157. NIYNewIncarnation = 3727;
  158. NIYOutOfBand = 3728;
  159. NIYMSS = 3729;
  160. ConnectionAborted = 3730;
  161. NotInitialized = 3731;
  162. DataDuplicatePrevComplete = 3732;
  163. DataDuplicatePrevPartial = 3733;
  164. DataDuplicateNextComplete = 3734;
  165. DataDuplicateNextPartial = 3735;
  166. TYPE
  167. (* Send buffer types *)
  168. SendData = IP.Packet;
  169. SendBuffer = POINTER TO RECORD
  170. next: SendBuffer;
  171. ofs, len: LONGINT; (* data[ofs..ofs+len-1] is valid *)
  172. seq: LONGINT; (* sequence number of byte data[ofs] (only valid if len # 0) *)
  173. pf: SET; (* flags of segment *)
  174. data: SendData (* size should be multiple of maxseg *)
  175. END;
  176. TYPE
  177. ISS = OBJECT
  178. VAR iss: LONGINT; (* next iss to use *)
  179. PROCEDURE Update(hz: LONGINT);
  180. BEGIN {EXCLUSIVE}
  181. INC(iss, ISSInc DIV hz)
  182. END Update;
  183. PROCEDURE Get(): LONGINT;
  184. VAR t: LONGINT;
  185. BEGIN {EXCLUSIVE}
  186. t := iss; INC(iss, ISSInc);
  187. RETURN t
  188. END Get;
  189. PROCEDURE &Init*(iss: LONGINT);
  190. BEGIN
  191. SELF.iss := iss
  192. END Init;
  193. END ISS;
  194. TYPE
  195. Timer = OBJECT (* temporary *)
  196. VAR
  197. lastFast, lastSlow: LONGINT; (* time of last execution *)
  198. (*lastTrace: LONGINT;*)
  199. now: LONGINT; (* current tcp "time" - read from other procedures, but only updated inside this object *)
  200. timer: ActiveTimers.Timer;
  201. PROCEDURE CallDelayedAck(p: Connection);
  202. BEGIN
  203. p.DelayedAck();
  204. END CallDelayedAck;
  205. PROCEDURE CallSlowTimer(p: Connection);
  206. BEGIN
  207. p.SlowTimer();
  208. END CallSlowTimer;
  209. PROCEDURE HandleTimeout;
  210. VAR t: LONGINT;
  211. BEGIN {EXCLUSIVE}
  212. t := Kernel.GetTicks();
  213. IF t - lastFast >= Kernel.second DIV FastPeriod THEN
  214. lastFast := t;
  215. pool.Enumerate(CallDelayedAck);
  216. END;
  217. IF t - lastSlow >= Kernel.second DIV SlowPeriod THEN
  218. lastSlow := t;
  219. pool.Enumerate(CallSlowTimer);
  220. issSource.Update(SlowPeriod);
  221. INC(now)
  222. END;
  223. timer.SetTimeout(HandleTimeout, Kernel.second DIV TimerPeriod)
  224. END HandleTimeout;
  225. (* Finalize timer by cancelling it *)
  226. PROCEDURE Finalize;
  227. BEGIN {EXCLUSIVE}
  228. timer.Finalize
  229. END Finalize;
  230. PROCEDURE &Init*;
  231. BEGIN
  232. now := 0;
  233. lastSlow := Kernel.GetTicks() - Kernel.second;
  234. lastFast := lastSlow; (*lastTrace := lastSlow;*)
  235. NEW(timer);
  236. timer.SetTimeout(HandleTimeout, Kernel.second DIV TimerPeriod)
  237. END Init;
  238. END Timer;
  239. TYPE
  240. (** Connection object.
  241. NOTE: Only one process should access a Connection!
  242. *)
  243. Connection* = OBJECT(Streams.Connection)
  244. VAR
  245. poolNext, parent, acceptNext: Connection;
  246. (* assigned interface *)
  247. int-: IP.Interface;
  248. (* local protocol address *)
  249. lport-: LONGINT;
  250. (* foreign protocol address *)
  251. fip-: IP.Adr;
  252. fport-: LONGINT;
  253. state*: SHORTINT; (* TCP state *)
  254. timer: ARRAY NumTimers OF LONGINT;
  255. rxtshift-: LONGINT; (* log(2) of rexmt exponential backoff *)
  256. rxtcur-: LONGINT; (* current retransmission timeout (ticks) *)
  257. dupacks-: LONGINT; (* number of consequtive duplicate acks received *)
  258. maxseg-: LONGINT; (* maximum segment size to send *)
  259. flags: SET; (* various connection and buffer flags *)
  260. error: LONGINT; (* error on connection (socket error) *)
  261. acceptable: LONGINT; (* number of connections that can be before acceptance *)
  262. (* send sequence *)
  263. snduna-: LONGINT; (* send unacknowledged *)
  264. sndnxt-: LONGINT; (* send next *)
  265. sndup: LONGINT; (* send urgent pointer *)
  266. sndwl1-: LONGINT; (* window update seg seq number *)
  267. sndwl2-: LONGINT; (* window update seg ack number *)
  268. iss-: LONGINT; (* initial send sequence number *)
  269. sndwnd-: LONGINT; (* send window *)
  270. sndmax-: LONGINT; (* highest sequence number sent - used to recognize retransmits *)
  271. (* receive sequence *)
  272. rcvwnd-: LONGINT; (* receive window *)
  273. rcvnxt-: LONGINT; (* receive next *)
  274. rcvup: LONGINT; (* receive urgent pointer *)
  275. irs-: LONGINT; (* initial receive sequence number *)
  276. rcvadv-: LONGINT; (* advertised window by other end *)
  277. (* congestion control *)
  278. sndcwnd-: LONGINT; (* congestion-controlled window *)
  279. sndssthresh-: LONGINT; (* sndcwnd threshold for slow start - exponential to linear switch *)
  280. (* transmit timing *)
  281. idle-: LONGINT; (* inactivity time *)
  282. rtt-: LONGINT; (* round trip time *)
  283. rtseq-: LONGINT; (* sequence number being timed *)
  284. srtt-: LONGINT; (* smoothed round trip time *)
  285. rttvar-: LONGINT; (* variance in round trip time *)
  286. rttmin-: LONGINT; (* minimum rtt allowed *)
  287. maxsndwnd: LONGINT; (* largest window peer has offered *)
  288. (* RFC 1323 *)
  289. sndscale: LONGINT; (* scaling for send window (0-14) *)
  290. rcvscale: LONGINT; (* scaling for receive window (0-14) *)
  291. requestrscale: LONGINT; (* our pending window scale *)
  292. requestedsscale: LONGINT; (* peer's pending window scale *)
  293. tsrecent: LONGINT; (* timestamp echo data *)
  294. tsrecentage: LONGINT; (* when last updated *)
  295. lastacksent-: LONGINT; (* sequence number of last ack field *)
  296. (* send buffer *)
  297. sndcc-: LONGINT; (* number of bytes in send buffer *)
  298. sndspace-: LONGINT; (* number of bytes that may still be added before buffer is full *)
  299. sndhead, sndtail: SendBuffer; (* queue of segments (contiguous and in order) *)
  300. sndcontig: SendData; (* maxseg size buffer to make data contiguous *)
  301. (* receive buffer *)
  302. rcvspace-: LONGINT; (* number of bytes that may still be received before buffer is considered full *)
  303. rcvhiwat-: LONGINT; (* receive high water mark (MaxRecvSpace) *)
  304. rcvhead, rcvreasm, rcvtail: Network.Buffer; (* queue of segments - see description at the beginning of this file *)
  305. rcvheadFragment: Network.Buffer; (* current fragment of rcvhead *)
  306. timeout: ActiveTimers.Timer;
  307. traceflow-: LONGINT;
  308. (* Initialization for internal use only. *)
  309. PROCEDURE &Init*;
  310. BEGIN
  311. state := Unused;
  312. END Init;
  313. (** Open a TCP connection (only use once per Connection instance).
  314. Use TCP.NilPort for lport to automatically assign an unused local port.
  315. *)
  316. PROCEDURE Open*(lport: LONGINT; fip: IP.Adr; fport: LONGINT; VAR res: WORD);
  317. BEGIN {EXCLUSIVE}
  318. ASSERT((state = Unused) & (lport >= 0) & (lport < 10000H) & (fport >= 0) & (fport < 10000H));
  319. IF timeSource # NIL THEN
  320. InitConnection(SELF);
  321. IF (~IP.IsNilAdr(fip)) & (fport # NilPort) THEN
  322. (* active open (connect) *)
  323. int := IP.InterfaceByDstIP(fip);
  324. IF int # NIL THEN
  325. SELF.fip := fip;
  326. pool.Add(SELF, lport, fport, res); (* add connection to connection pool *)
  327. IF res = Ok THEN (* address assignment ok, now start the connection *)
  328. Machine.AtomicInc(NTCPConnectAttempt);
  329. state := SynSent; timer[Keep] := KeepInit;
  330. iss := issSource.Get();
  331. snduna := iss; sndnxt := iss; sndmax := iss; sndup := iss;
  332. Output(SELF)
  333. END;
  334. ELSE
  335. res := NoInterface;
  336. END;
  337. ELSE
  338. (* passive open (listen) *)
  339. ASSERT((fport = NilPort) & (IP.IsNilAdr(fip)));
  340. SELF.int := NIL;
  341. SELF.fip := IP.NilAdr;
  342. pool.Add(SELF, lport, NilPort, res);
  343. IF res = Ok THEN
  344. INCL(flags, AcceptConn);
  345. acceptable := Acceptable;
  346. state := Listen;
  347. END
  348. END;
  349. IF TraceProtocol THEN
  350. TraceTCP("Open", SELF, empty^, empty^, 0, 0, 0)
  351. END
  352. ELSE
  353. res := NotInitialized;
  354. END
  355. END Open;
  356. (** Send data on a TCP connection. *)
  357. PROCEDURE Send*(CONST data: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  358. VAR buf: SendBuffer; len0: LONGINT;
  359. BEGIN {EXCLUSIVE}
  360. IF StrongChecks THEN Invariant(SELF) END;
  361. ASSERT(ofs+len <= LEN(data)); (* index check *)
  362. LOOP
  363. IF len <= 0 THEN EXIT END;
  364. IF len <= maxseg THEN len0 := len ELSE len0 := maxseg END;
  365. IF ~((state IN {Established, CloseWait}) & (sndspace >= len0)) THEN (* can not send immediately *)
  366. AWAIT(((state IN {Established, CloseWait}) & (sndspace >= len0)) OR ~(state IN {SynSent..CloseWait}));
  367. IF StrongChecks THEN Invariant(SELF) END;
  368. IF ~(state IN {SynSent..CloseWait}) THEN (* connection broken *)
  369. IF error # Ok THEN res := error ELSE res := NotConnected END;
  370. RETURN
  371. END
  372. END;
  373. buf := sndtail;
  374. IF LEN(buf.data^) - (buf.ofs+buf.len) >= len0 THEN (* last buffer has space for data *)
  375. IF SystemMove THEN
  376. SYSTEM.MOVE(ADDRESSOF(data[ofs]), ADDRESSOF(buf.data[buf.ofs+buf.len]), len0)
  377. ELSE
  378. Network.Copy(data, buf.data^, ofs, buf.ofs+buf.len, len0)
  379. END;
  380. INC(buf.len, len0)
  381. ELSE (* last buffer has no space for data *)
  382. buf := buf.next;
  383. IF buf # sndhead THEN (* is free buffer *)
  384. ASSERT((buf.ofs = 0) & (buf.len = 0)); (* buffer must be unused *)
  385. ASSERT(LEN(buf.data^) >= len0) (* index check *)
  386. ELSE
  387. Machine.AtomicInc(NTCPNewBufs);
  388. NEW(buf); NEW(buf.data, MSS * SegsPerBuf);
  389. IF ~NewZeros THEN buf.ofs := 0; END;
  390. buf.next := sndtail.next; sndtail.next := buf;
  391. ASSERT(LEN(buf.data^) >= len0) (* index check *)
  392. END;
  393. IF SystemMove THEN
  394. SYSTEM.MOVE(ADDRESSOF(data[ofs]), ADDRESSOF(buf.data[0]), len0)
  395. ELSE
  396. Network.Copy(data, buf.data^, ofs, 0, len0)
  397. END;
  398. buf.len := len0; sndtail := buf
  399. END;
  400. INC(sndcc, len0); DEC(sndspace, len0);
  401. Output(SELF);
  402. INC(ofs, len0); DEC(len, len0)
  403. END;
  404. IF TraceProtocol THEN
  405. TraceTCP("Send", SELF, empty^, data, 0, ofs, len)
  406. END;
  407. res := Ok
  408. END Send;
  409. (** Receive data on a TCP connection. The data parameter specifies the buffer. The ofs parameters specify the position in the buffer where data should be received (usually 0), and the size parameters specifies how many bytes of data can be received in the buffer. The min parameter specifies the minimum number of bytes to receive before Receive returns and must by <= size. The len parameter returns the number of bytes received, and the res parameter returns 0 if ok, or a non-zero error code otherwise (e.g. if the connection is closed by the communication partner, or by a call of the Close method). *)
  410. PROCEDURE Receive*(VAR data: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len: LONGINT; VAR res: WORD);
  411. VAR
  412. buf: Network.Buffer;
  413. rlen: LONGINT;
  414. BEGIN {EXCLUSIVE}
  415. IF StrongChecks THEN Invariant(SELF) END;
  416. ASSERT((ofs >= 0) & (ofs+size <= LEN(data)) & (min <= size)); (* parameter consistency check *)
  417. len := 0;
  418. LOOP
  419. WHILE (rcvhead # NIL) & (rcvhead # rcvreasm) & (size > 0) DO
  420. IF rcvhead.nextFragment = NIL THEN
  421. (* read all available data until user buffer is full *)
  422. rlen := MIN(rcvhead.len, size);
  423. IF SystemMove THEN
  424. SYSTEM.MOVE(ADDRESSOF(rcvhead.data[rcvhead.ofs]), ADDRESSOF(data[ofs]), rlen);
  425. ELSE
  426. Network.Copy(rcvhead.data, data, rcvhead.ofs, ofs, rlen);
  427. END;
  428. INC(len, rlen);
  429. INC(ofs, rlen);
  430. DEC(size, rlen);
  431. INC(rcvhead.ofs, rlen);
  432. DEC(rcvhead.len, rlen);
  433. INC(rcvhead.int, rlen);
  434. INC(rcvspace, rlen);
  435. IF rcvhead.len = 0 THEN
  436. (* go to next buffer *)
  437. buf := rcvhead;
  438. rcvhead := rcvhead.next;
  439. IF rcvhead # NIL THEN
  440. rcvhead.prev := NIL;
  441. END;
  442. Network.ReturnBuffer(buf);
  443. Output(SELF); (* enable sending window update segment *)
  444. END;
  445. ELSE
  446. (* rcvhead has fragments *)
  447. (* read all available data until user buffer is full *)
  448. IF rcvheadFragment = NIL THEN
  449. rcvheadFragment := rcvhead;
  450. END;
  451. rlen := MIN(rcvheadFragment.len, size);
  452. IF SystemMove THEN
  453. SYSTEM.MOVE(ADDRESSOF(rcvheadFragment.data[rcvheadFragment.ofs]), ADDRESSOF(data[ofs]), rlen);
  454. ELSE
  455. Network.Copy(rcvheadFragment.data, data, rcvheadFragment.ofs, ofs, rlen);
  456. END;
  457. INC(len, rlen);
  458. INC(ofs, rlen);
  459. DEC(size, rlen);
  460. INC(rcvheadFragment.ofs, rlen);
  461. DEC(rcvheadFragment.len, rlen);
  462. INC(rcvheadFragment.int, rlen);
  463. INC(rcvspace, rlen);
  464. IF rcvheadFragment.len = 0 THEN
  465. IF rcvheadFragment.nextFragment # NIL THEN
  466. (* go to next fragment *)
  467. rcvheadFragment := rcvheadFragment.nextFragment;
  468. ELSE
  469. (* go to next buffer *)
  470. buf := rcvhead;
  471. rcvhead := rcvhead.next;
  472. IF rcvhead # NIL THEN
  473. rcvhead.prev := NIL;
  474. END;
  475. Network.ReturnBuffer(buf);
  476. Output(SELF); (* enable sending window update segment *)
  477. END;
  478. END;
  479. END;
  480. END;
  481. IF size = 0 THEN
  482. (* user buffer full *)
  483. EXIT;
  484. END;
  485. IF len >= min THEN
  486. (* enough was read *)
  487. EXIT;
  488. ELSE
  489. (* await available data or closed connection state *)
  490. AWAIT(((rcvhead # NIL) & (rcvhead # rcvreasm)) OR ~(state IN {SynSent, SynReceived, Established, FinWait1, FinWait2}));
  491. IF StrongChecks THEN Invariant(SELF) END;
  492. IF (rcvhead # NIL) & (rcvhead # rcvreasm) THEN
  493. (* new data available, start again with LOOP *)
  494. ELSE
  495. (* no data available, and no more can arrive, as we've seen the FIN *)
  496. IF error # Ok THEN res := error ELSE res := Streams.EOF (* end of file *) END;
  497. RETURN;
  498. END;
  499. END;
  500. END;
  501. IF StrongChecks THEN Invariant(SELF) END;
  502. IF TraceProtocol THEN
  503. TraceTCP("Receive", SELF, empty^, data, 0, ofs, len)
  504. END;
  505. res := Ok
  506. END Receive;
  507. (** Enable or disable delayed send (Nagle algorithm).
  508. If enabled, the sending of a segment is delayed if it is not filled by one call to Send, in order to be able to be filled
  509. by further calls to Send. This is the default option.
  510. If disabled, a segment is sent immediatly after a call to Send, even if it is not filled. This option is normally chosen
  511. by applications like telnet or VNC client, which send verly little data but shall not be delayed.
  512. *)
  513. PROCEDURE DelaySend*(enable: BOOLEAN);
  514. BEGIN {EXCLUSIVE}
  515. IF enable THEN
  516. EXCL(flags, NoDelay);
  517. ELSE
  518. INCL(flags, NoDelay);
  519. END;
  520. END DelaySend;
  521. (** Enable or disable keep-alive. (default: disabled) *)
  522. PROCEDURE KeepAlive*(enable: BOOLEAN);
  523. BEGIN {EXCLUSIVE}
  524. IF enable THEN
  525. INCL(flags, DoKeepAlive);
  526. ELSE
  527. EXCL(flags, DoKeepAlive);
  528. END;
  529. END KeepAlive;
  530. (** Return number of bytes that may be read without blocking. *)
  531. PROCEDURE Available*(): LONGINT;
  532. VAR
  533. len: LONGINT;
  534. item: Network.Buffer;
  535. fragmentBuffer: Network.Buffer;
  536. reassembledLength: LONGINT;
  537. BEGIN {EXCLUSIVE}
  538. len := 0;
  539. item := rcvhead;
  540. WHILE(item # NIL) & (item # rcvreasm) DO
  541. IF item.nextFragment # NIL THEN
  542. INC(len, item.len);
  543. ELSE
  544. (* fragmented packet *)
  545. fragmentBuffer := item;
  546. reassembledLength := 0;
  547. WHILE fragmentBuffer # NIL DO
  548. INC(len, fragmentBuffer.len);
  549. fragmentBuffer := fragmentBuffer.nextFragment;
  550. END;
  551. END;
  552. item := item.next;
  553. END;
  554. RETURN len;
  555. END Available;
  556. (** Return connection state. *)
  557. PROCEDURE State*(): LONGINT;
  558. BEGIN {EXCLUSIVE}
  559. IF (state IN FinStates) & (rcvhead # NIL) & (rcvhead.len # 0) THEN (* workaround for client errors *)
  560. IF state = CloseWait THEN (* act as if we haven't seen a FIN yet *)
  561. RETURN Established
  562. ELSE
  563. RETURN FinWait1
  564. END
  565. ELSE
  566. RETURN state
  567. END
  568. END State;
  569. (** Wait until the connection state is either in the good or bad set, up to "ms" milliseconds. *)
  570. PROCEDURE AwaitState*(good, bad: SET; ms: LONGINT; VAR res: WORD);
  571. BEGIN {EXCLUSIVE}
  572. IF ~(state IN (good+bad)) THEN
  573. IF ms # -1 THEN
  574. IF timeout = NIL THEN NEW(timeout) END;
  575. timeout.SetTimeout(SELF.HandleTimeout, ms);
  576. END;
  577. EXCL(flags, Timeout);
  578. AWAIT((state IN (good+bad)) OR (Timeout IN flags));
  579. IF ms # -1 THEN timeout.CancelTimeout(); END
  580. END;
  581. IF state IN good THEN
  582. res := Ok
  583. ELSIF state IN bad THEN
  584. res := NotConnected
  585. ELSE
  586. res := TimedOut
  587. END
  588. END AwaitState;
  589. PROCEDURE HandleTimeout;
  590. BEGIN {EXCLUSIVE}
  591. INCL(flags, Timeout)
  592. END HandleTimeout;
  593. (** Close a TCP connection (half-close). *)
  594. PROCEDURE Close*;
  595. BEGIN {EXCLUSIVE}
  596. IF state < Established THEN
  597. CloseConnection(SELF)
  598. ELSIF FALSE (* linger *) THEN
  599. Drop(SELF, 0)
  600. ELSE
  601. UsrClosed(SELF);
  602. IF state # Closed THEN Output(SELF) END
  603. END;
  604. IF TraceProtocol THEN
  605. TraceTCP("Close", SELF, empty^, empty^, 0, 0, 0)
  606. END
  607. END Close;
  608. (** Discard a TCP connection (shutdown). *)
  609. PROCEDURE Discard*;
  610. BEGIN {EXCLUSIVE}
  611. IF state < Established THEN
  612. CloseConnection(SELF)
  613. ELSE
  614. Drop(SELF, ConnectionReset) (* ??? *)
  615. END;
  616. IF TraceProtocol THEN
  617. TraceTCP("Discard", SELF, empty^, empty^, 0, 0, 0)
  618. END
  619. END Discard;
  620. (** Accept a client waiting on a listening connection. Blocks until a client is available or the connection is closed. *)
  621. PROCEDURE Accept*(VAR client: Connection; VAR res: WORD);
  622. BEGIN {EXCLUSIVE}
  623. AWAIT((state # Listen) OR (acceptNext # NIL));
  624. IF acceptNext # NIL THEN
  625. client := acceptNext; acceptNext := acceptNext.acceptNext;
  626. INC(acceptable); res := Ok
  627. ELSE
  628. client := NIL; res := ConnectionRefused
  629. END
  630. END Accept;
  631. (** Return TRUE iff a listening connection has clients waiting to be accepted. *)
  632. PROCEDURE Requested*(): BOOLEAN;
  633. BEGIN {EXCLUSIVE}
  634. RETURN (state = Listen) & (acceptNext # NIL)
  635. END Requested;
  636. (* Process a received segment for the current Connection. *)
  637. PROCEDURE Input(int: IP.Interface; fip: IP.Adr; hdrLen: LONGINT; buffer: Network.Buffer);
  638. VAR
  639. bufferQueued: BOOLEAN; (* was buffer queued by ProcessInput() ? *)
  640. p: Connection;
  641. BEGIN {EXCLUSIVE}
  642. (* to do: move header prediction code here *)
  643. IF StrongChecks THEN Invariant(SELF) END;
  644. bufferQueued := FALSE;
  645. IF AcceptConn IN flags THEN
  646. IF acceptable > 0 THEN
  647. NEW(p); InitConnection(p); (* fig. 28.7 *)
  648. p.int := int;
  649. p.fip := fip;
  650. p.state := Listen; p.parent := SELF;
  651. ProcessInput(p, hdrLen, buffer, TRUE, bufferQueued);
  652. IF p.state = SynReceived THEN (* packet was accepted *)
  653. DEC(acceptable) (* limit number of "temporary" Connections *)
  654. END
  655. ELSE
  656. Machine.AtomicInc(NTCPUnacceptable)
  657. END
  658. ELSE
  659. IF SELF = nilpcb THEN
  660. (* set info for "Respond" *)
  661. SELF.int := int;
  662. SELF.fport := Network.GetNet2(buffer.data, buffer.ofs);
  663. SELF.lport := Network.GetNet2(buffer.data, buffer.ofs+2);
  664. END;
  665. IF SELF.int # int THEN
  666. (* packet must be received by interface attached to this connection *)
  667. Error(WrongInterface, 0, SELF);
  668. ELSE
  669. SELF.fip := fip;
  670. ProcessInput(SELF, hdrLen, buffer, FALSE, bufferQueued);
  671. END;
  672. END;
  673. IF StrongChecks THEN Invariant(SELF) END;
  674. IF ~bufferQueued THEN
  675. Network.ReturnBuffer(buffer);
  676. END;
  677. END Input;
  678. (* Schedule a delayed ack. *)
  679. PROCEDURE DelayedAck;
  680. BEGIN {EXCLUSIVE}
  681. IF StrongChecks THEN Invariant(SELF) END;
  682. IF DelAck IN flags THEN
  683. flags := (flags - {DelAck}) + {AckNow};
  684. Machine.AtomicInc(NTCPDelAck);
  685. Output(SELF)
  686. END
  687. END DelayedAck;
  688. (* Schedule a slow timer event (fig. 25.8). *)
  689. PROCEDURE SlowTimer;
  690. VAR dropit: BOOLEAN;
  691. oldie: LONGINT;
  692. BEGIN {EXCLUSIVE}
  693. oldie := sndnxt;
  694. IF StrongChecks THEN Invariant(SELF) END;
  695. IF Expired(timer[ReXmt]) THEN (* fig. 25.26 *)
  696. INC(rxtshift);
  697. IF rxtshift > MaxRxtShift THEN
  698. rxtshift := MaxRxtShift; Error(TimedOut, 0, SELF); Drop(SELF, TimedOut)
  699. ELSE
  700. Machine.AtomicInc(NTCPReXmtTimer);
  701. RangeSet(rxtcur, (ASH(srtt, -RTTShift) + rttvar) * backoff[rxtshift], rttmin, ReXmtMax);
  702. timer[ReXmt] := rxtcur;
  703. IF rxtshift > MaxRxtShift DIV 4 THEN
  704. (* to do: drop current route *)
  705. INC(rttvar, ASH(srtt, -RTTShift));
  706. srtt := 0
  707. END;
  708. sndnxt := snduna; rtt := 0;
  709. sndcwnd := maxseg; dupacks := 0;
  710. sndssthresh := MAX(MIN(sndwnd, sndcwnd) DIV 2 DIV maxseg, 2) * maxseg;
  711. IF TraceCongestion THEN
  712. KernelLog.String("ST sndssthresh := "); KernelLog.Int(sndssthresh, 1); KernelLog.Ln
  713. END;
  714. Output(SELF)
  715. END
  716. END;
  717. IF Expired(timer[Persist]) THEN (* fig. 25.13 *)
  718. Machine.AtomicInc(NTCPPersistTimer);
  719. IF (rxtshift = MaxRxtShift) & ((idle >= MaxPersistIdle) OR (idle >= (ASH(srtt, -RTTShift) + rttvar) * totbackoff)) THEN
  720. Machine.AtomicInc(NTCPPersistDrop); (* vol. 3 fig. 14.17 *)
  721. Drop(SELF, TimedOut)
  722. ELSE
  723. SetPersist(SELF); INCL(flags, Force); Output(SELF); EXCL(flags, Force)
  724. END
  725. END;
  726. traceflow := 0;
  727. IF Expired(timer[Keep]) THEN (* fig. 25.16 *)
  728. Machine.AtomicInc(NTCPKeepTimer); dropit := FALSE;
  729. IF state >= Established THEN
  730. IF (DoKeepAlive IN flags) & (state <= CloseWait) THEN
  731. IF idle < KeepIdle + MaxIdle THEN
  732. traceflow := 1;
  733. Machine.AtomicInc(NTCPKeepProbe);
  734. Respond(SELF, rcvnxt, snduna-1, {});
  735. timer[Keep] := KeepIntvl
  736. ELSE
  737. traceflow := 2;
  738. dropit := TRUE; Error(TimeOutKeepAlive, 0, SELF)
  739. END
  740. ELSE
  741. traceflow := 3;
  742. timer[Keep] := KeepIdle
  743. END
  744. ELSE
  745. traceflow := 4;
  746. dropit := TRUE; Error(TimeoutEstablished, 0, SELF)
  747. END;
  748. IF dropit THEN Drop(SELF, TimedOut) END
  749. END;
  750. IF Expired(timer[MSL2]) THEN (* fig. 25.10 *)
  751. IF (state # TimeWait) & (idle <= MaxIdle) THEN
  752. timer[MSL2] := KeepIntvl
  753. ELSE
  754. IF state = FinWait2 THEN Machine.AtomicInc(NTCPFinWait2Timer) ELSE Machine.AtomicInc(NTCPTimeWaitTimer) END;
  755. CloseConnection(SELF)
  756. END
  757. END;
  758. INC(idle);
  759. IF rtt # 0 THEN INC(rtt) END;
  760. (* check if interface wasn't closed/removed in meantime *)
  761. IF (int # NIL) & (int.closed) THEN
  762. Drop(SELF, InterfaceClosed);
  763. END;
  764. END SlowTimer;
  765. (* Finalize the Connection object *)
  766. PROCEDURE Finalize;
  767. BEGIN
  768. IF timeout # NIL THEN timeout.Finalize; END;
  769. Discard();
  770. END Finalize;
  771. END Connection;
  772. TYPE
  773. ConnectionHandler* = PROCEDURE {DELEGATE} (p: Connection);
  774. ConnectionPool* = OBJECT
  775. VAR
  776. eport: LONGINT;
  777. table: ARRAY HashTableSize OF Connection;
  778. (* Initialization for internal use only. *)
  779. PROCEDURE &Init*;
  780. VAR i: LONGINT;
  781. BEGIN
  782. FOR i:= 0 TO HashTableSize-1 DO
  783. table[i] := NIL;
  784. END;
  785. eport := MinEphemeralPort;
  786. END Init;
  787. (* Finalize all connections in this pool *)
  788. PROCEDURE Finalize;
  789. VAR i: LONGINT;
  790. BEGIN
  791. FOR i:= 0 TO HashTableSize-1 DO
  792. WHILE table[i] # NIL DO
  793. table[i].Finalize();
  794. END;
  795. END;
  796. END Finalize;
  797. (* Look for the specified Connection. *)
  798. PROCEDURE Lookup(lport, fport: LONGINT; fip: IP.Adr): Connection;
  799. VAR
  800. item: Connection;
  801. BEGIN
  802. item := table[HashPool(lport, fport, fip)];
  803. WHILE (item # NIL) & ((~IP.AdrsEqual(item.fip, fip)) OR (item.fport # fport) OR (item.lport # lport)) DO
  804. item := item.poolNext;
  805. END;
  806. IF item = NIL THEN
  807. RETURN nilpcb;
  808. ELSE
  809. RETURN item;
  810. END;
  811. END Lookup;
  812. (** Enumerate all Connections. Only for tracing, due to concurrent updates data may be stale. *)
  813. PROCEDURE Enumerate*(handle: ConnectionHandler);
  814. VAR
  815. i: LONGINT;
  816. item: Connection;
  817. BEGIN
  818. FOR i:= 0 TO HashTableSize-1 DO
  819. item := table[i];
  820. WHILE item # NIL DO
  821. handle(item);
  822. item := item.poolNext;
  823. END;
  824. END;
  825. END Enumerate;
  826. (* Add the connection p to the pool (attach). Assumes the caller has exclusive access to p.
  827. IF (fport = NilPort) & (fip = IP.NilAdr), a listening connection is assumed.
  828. ELSE an active open is assumed.
  829. IF (lport = NilPort), an ephemeral port is assigned.
  830. *)
  831. PROCEDURE Add(p: Connection; lport, fport: LONGINT; VAR res: WORD);
  832. VAR i, sport: LONGINT;
  833. BEGIN {EXCLUSIVE}
  834. IF ((fport # NilPort) & (IP.IsNilAdr(p.fip))) OR (* workaround for XOR *)
  835. ((fport = NilPort) & (~IP.IsNilAdr(p.fip))) THEN
  836. (* both must be "nil" or both must not be "nil" *)
  837. res := InvalidParameter;
  838. Error(res, 0, p);
  839. RETURN;
  840. END;
  841. IF lport = NilPort THEN
  842. (* find an ephemeral port *)
  843. sport := eport;
  844. LOOP
  845. lport := eport;
  846. INC(eport);
  847. IF eport > MaxEphemeralPort THEN
  848. eport := MinEphemeralPort;
  849. END;
  850. IF Lookup(lport, fport, p.fip) = nilpcb THEN
  851. (* found port that is not in use *)
  852. EXIT;
  853. END;
  854. IF eport = sport THEN
  855. res := AllPortsInUse;
  856. Error(res, 0, p);
  857. RETURN;
  858. END;
  859. END;
  860. ELSE
  861. IF Lookup(lport, fport, p.fip) # nilpcb THEN
  862. res := AddressInUse;
  863. Error(res, 0, p);
  864. RETURN;
  865. END;
  866. END;
  867. p.lport := lport;
  868. p.fport := fport;
  869. (* add to pool *)
  870. i := HashPool(lport, fport, p.fip);
  871. p.poolNext := table[i];
  872. table[i] := p;
  873. res := Ok;
  874. END Add;
  875. (* Remove a Connection from the queue (detach), making its address re-usable. *)
  876. PROCEDURE Remove(p: Connection);
  877. VAR
  878. i: LONGINT;
  879. item: Connection;
  880. BEGIN {EXCLUSIVE}
  881. i := HashPool(p.lport, p.fport, p.fip);
  882. IF table[i] # NIL THEN
  883. IF table[i] = p THEN
  884. (* remove first item *)
  885. table[i] := table[i].poolNext;
  886. RETURN;
  887. ELSE
  888. (* search list for connection *)
  889. item := table[i];
  890. WHILE (item.poolNext # NIL) & (item.poolNext # p) DO
  891. item := item.poolNext;
  892. END;
  893. IF item.poolNext # NIL THEN
  894. (* found - remove *)
  895. item.poolNext := item.poolNext.poolNext;
  896. RETURN;
  897. END;
  898. END;
  899. END;
  900. Error(ConnectionGone, 0, p); (* pcb gone, e.g. Rst received *)
  901. END Remove;
  902. END ConnectionPool;
  903. TYPE
  904. (** Install a procedure to be called when no matching port was found for an incoming connection request.
  905. The buffer MUST NOT be returned by the listener, it is returned automatically by the caller afterwards.
  906. *)
  907. PacketDumpListener* = PROCEDURE (fip: IP.Adr; buffer: Network.Buffer);
  908. VAR
  909. pool*: ConnectionPool; (* pool of all Connections *)
  910. timeSource: Timer; (* global timer *)
  911. issSource: ISS; (* source for ISS numbers *)
  912. lastpcb: Connection; (* cache last used pcb (never NIL). Note that it is possible that a deleted pcb can be ressurrected by a packet arriving for it. As soon as a packet for another connection arrives, the deleted pcb will vanish. *)
  913. nilpcb: Connection; (* never NIL *)
  914. empty: SendData; (* never NIL *)
  915. backoff: ARRAY MaxRxtShift+1 OF LONGINT; (* exponential backoff multipliers *)
  916. totbackoff: LONGINT;
  917. outflags: ARRAY NumStates OF SET; (* output header flags *)
  918. (* TCP counters *)
  919. NTCPError-: ARRAY NumErrors OF LONGINT;
  920. NTCPConnectAttempt-, NTCPPersistTimer-, NTCPFinWait2Timer-, NTCPSendProbe-, NTCPReXmtPack-,
  921. NTCPReXmtByte-, NTCPSendPack-, NTCPSendByte-, NTCPAcks-, NTCPSendCtrl-, NTCPSendUrg-,
  922. NTCPSendWinUp-, NTCPSegsTimed-, NTCPSendTotal-, NTCPKeepTimer-, NTCPKeepProbe-,
  923. NTCPReXmtTimer-, NTCPRcvTotal-, NTCPRcvOptions-, NTCPCacheMiss-, NTCPPredAck-, NTCPAckPack-,
  924. NTCPAckByte-, NTCPPredData-, NTCPRcvPackFast-, NTCPRcvByteFast-, NTCPConnects-, NTCPRcvWinProbe-,
  925. NTCPDrops-, NTCPRcvWinUpd-, NTCPRTTUpdated-, NTCPDelAck-, NTCPConnDrops-, NTCPClosed-, NTCPSplitBuffer-,
  926. NTCPRcvPackSlow-, NTCPRcvByteSlow-, NTCPNewBufs-, NTCPTimeWaitTimer-,
  927. NTCPUnacceptable-, NTCPAccepts-, NTCPPersistDrop-: LONGINT;
  928. trace: BOOLEAN;
  929. packetDumpListener : PacketDumpListener;
  930. (* Trace installer *)
  931. (** Install a procedure to be called when no matching port was found for an incoming connection request.
  932. The buffer doesn't have to be returned by the listener, it is returned automatically by the caller afterwards.
  933. *)
  934. PROCEDURE SetDefaultListener*(pdl : PacketDumpListener);
  935. BEGIN
  936. packetDumpListener := pdl
  937. END SetDefaultListener;
  938. (* --- Utility procedures. *)
  939. PROCEDURE Invariant(p: Connection);
  940. VAR
  941. rcvbuf: Network.Buffer;
  942. sndbuf: SendBuffer;
  943. found: BOOLEAN;
  944. BEGIN
  945. IF StrongChecks & (p # nilpcb) THEN
  946. (* receive buffers *)
  947. rcvbuf := p.rcvhead;
  948. IF rcvbuf # NIL THEN
  949. (* not empty *)
  950. ASSERT((rcvbuf.len > 0) OR (Fin IN rcvbuf.set));
  951. ASSERT(rcvbuf.prev = NIL);
  952. IF rcvbuf.next = NIL THEN
  953. (* the only buffer *)
  954. ASSERT(p.rcvtail = rcvbuf);
  955. ELSE
  956. rcvbuf := rcvbuf.next;
  957. IF rcvbuf.next = NIL THEN
  958. (* 2 buffers *)
  959. ASSERT(rcvbuf.prev.next = rcvbuf);
  960. ASSERT(p.rcvtail = rcvbuf);
  961. ELSE
  962. (* check chain (more than 2 buffers *)
  963. REPEAT
  964. ASSERT(rcvbuf.next.prev = rcvbuf);
  965. ASSERT(rcvbuf.prev.next = rcvbuf);
  966. rcvbuf := rcvbuf.next;
  967. UNTIL rcvbuf.next = NIL;
  968. (* last buffer *)
  969. ASSERT(p.rcvtail = rcvbuf);
  970. END;
  971. END;
  972. END;
  973. (* send buffers *)
  974. sndbuf := p.sndhead; found := FALSE;
  975. LOOP
  976. found := found OR (sndbuf = p.sndtail);
  977. sndbuf := sndbuf.next;
  978. ASSERT(sndbuf # NIL);
  979. IF sndbuf = p.sndhead THEN EXIT END;
  980. ASSERT(~found OR ((sndbuf.ofs = 0) & (sndbuf.len = 0)))
  981. END;
  982. ASSERT(found);
  983. END
  984. END Invariant;
  985. (* Hash function for ConnectionPool *)
  986. PROCEDURE HashPool(lport, fport: LONGINT; fip:IP.Adr): LONGINT;
  987. VAR
  988. i: LONGINT;
  989. hash: LONGINT;
  990. BEGIN
  991. (* hash := (lport + fport + fip) MOD HashTableSize; *)
  992. hash := lport + fport;
  993. CASE fip.usedProtocol OF
  994. IP.IPv4:
  995. INC(hash, fip.ipv4Adr);
  996. |IP.IPv6:
  997. FOR i := 0 TO 15 DO
  998. INC(hash, ORD(fip.ipv6Adr[i]));
  999. END;
  1000. ELSE
  1001. END;
  1002. RETURN hash MOD HashTableSize;
  1003. END HashPool;
  1004. (*
  1005. (* Hash function for ConnectionPool. *)
  1006. PROCEDURE -HashPool(lport, fport: LONGINT; fip: IP.Adr): LONGINT;
  1007. CODE {SYSTEM.i386}
  1008. (* hash := (lport + fport + fip) MOD HashTableSize; *)
  1009. POP ECX
  1010. POP EBX
  1011. POP EAX
  1012. ; Convert IP to host byte order
  1013. XCHG CL, CH
  1014. ROL ECX, 16
  1015. XCHG CL, CH
  1016. ; Calculate sum
  1017. ADD EAX, EBX
  1018. ADD EAX, ECX
  1019. ; MOD operation
  1020. MOV EBX, HashTableSize
  1021. XOR EDX, EDX
  1022. DIV EBX
  1023. MOV EAX, EDX
  1024. END HashPool;
  1025. *)
  1026. (* Set x to val, but keep it between min and max. *)
  1027. PROCEDURE RangeSet(VAR x: LONGINT; val, min, max: LONGINT);
  1028. BEGIN
  1029. IF val < min THEN x := min
  1030. ELSIF val > max THEN x := max
  1031. ELSE x := val
  1032. END
  1033. END RangeSet;
  1034. (*
  1035. PROCEDURE -Min(a, b: LONGINT): LONGINT;
  1036. CODE {SYSTEM.i386}
  1037. POP EBX
  1038. POP EAX
  1039. CMP EAX, EBX
  1040. JLE end
  1041. MOV EAX, EBX
  1042. end:
  1043. END Min;
  1044. PROCEDURE -Max(a, b: LONGINT): LONGINT;
  1045. CODE {SYSTEM.i386}
  1046. POP EBX
  1047. POP EAX
  1048. CMP EAX, EBX
  1049. JGE end
  1050. MOV EAX, EBX
  1051. end:
  1052. END Max;
  1053. *)
  1054. PROCEDURE WriteTime(t: LONGINT);
  1055. VAR s: ARRAY 8 OF CHAR;
  1056. BEGIN
  1057. KernelLog.Int(t DIV Kernel.second, 1);
  1058. s[0] := "."; t := (t MOD Kernel.second)*1000 DIV Kernel.second;
  1059. s[1] := CHR(48+t DIV 100 MOD 10); s[2] := CHR(48+t DIV 10 MOD 10);
  1060. s[3] := CHR(48+t MOD 10); s[4] := 0X;
  1061. KernelLog.String(s)
  1062. END WriteTime;
  1063. (* TCP error function. *)
  1064. PROCEDURE Error(err: WORD; n: LONGINT; p: Connection);
  1065. BEGIN
  1066. IF trace THEN
  1067. KernelLog.Enter; KernelLog.String("TCP: "); WriteTime(Kernel.GetTicks());
  1068. KernelLog.String(" result "); KernelLog.Int(err, 1);
  1069. KernelLog.Char(" "); KernelLog.Int(n, 1); KernelLog.Exit
  1070. END;
  1071. IF TraceError & (p # NIL) THEN TraceTCP("", p, empty^, empty^, 0, 0, 0) END;
  1072. Machine.AtomicInc(NTCPError[0]); Machine.AtomicInc(NTCPError[err-MinError])
  1073. END Error;
  1074. (* Calculate and store new value for persist timer. *)
  1075. PROCEDURE SetPersist(p: Connection);
  1076. BEGIN
  1077. ASSERT(p.timer[ReXmt] = 0);
  1078. RangeSet(p.timer[Persist], (p.srtt DIV 4 + p.rttvar) DIV 2 * backoff[p.rxtshift], PersMin, PersMax);
  1079. IF p.rxtshift < MaxRxtShift THEN INC(p.rxtshift) END
  1080. END SetPersist;
  1081. (* Trace Connection fields. *)
  1082. PROCEDURE TraceConnection(p: Connection);
  1083. VAR i: LONGINT;
  1084. BEGIN
  1085. IF Trace THEN
  1086. KernelLog.String(" state=");
  1087. CASE p.state OF
  1088. Closed: KernelLog.String("Closed")
  1089. |Listen: KernelLog.String("Listen")
  1090. |SynSent: KernelLog.String("SynSent")
  1091. |SynReceived: KernelLog.String("SynReceived")
  1092. |Established: KernelLog.String("Established")
  1093. |CloseWait: KernelLog.String("CloseWait")
  1094. |FinWait1: KernelLog.String("FinWait1")
  1095. |Closing: KernelLog.String("Closing")
  1096. |LastAck: KernelLog.String("LastAck")
  1097. |FinWait2: KernelLog.String("FinWait2")
  1098. |TimeWait: KernelLog.String("TimeWait")
  1099. END;
  1100. KernelLog.String(" maxseg="); KernelLog.Int(p.maxseg, 1);
  1101. KernelLog.String(" flags={");
  1102. IF AckNow IN p.flags THEN KernelLog.String(" AckNow") END;
  1103. IF DelAck IN p.flags THEN KernelLog.String(" DelAck") END;
  1104. IF NoDelay IN p.flags THEN KernelLog.String(" NoDelay") END;
  1105. IF SentFin IN p.flags THEN KernelLog.String(" SentFin") END;
  1106. IF Force IN p.flags THEN KernelLog.String(" Force") END;
  1107. IF RcvdScale IN p.flags THEN KernelLog.String(" RcvdScale") END;
  1108. IF RcvdTstmp IN p.flags THEN KernelLog.String(" RcvdTstmp") END;
  1109. IF ReqScale IN p.flags THEN KernelLog.String(" ReqScale") END;
  1110. IF ReqTstmp IN p.flags THEN KernelLog.String(" ReqTstmp") END;
  1111. IF DoKeepAlive IN p.flags THEN KernelLog.String(" DoKeepAlive") END;
  1112. IF AcceptConn IN p.flags THEN KernelLog.String(" AcceptConn") END;
  1113. FOR i := 11 TO 31 DO
  1114. IF i IN p.flags THEN KernelLog.Char(" "); KernelLog.Int(i, 1) END
  1115. END;
  1116. KernelLog.String(" } error="); KernelLog.Int(p.error, 1);
  1117. KernelLog.Ln;
  1118. KernelLog.String(" iss="); KernelLog.Int(p.iss, 1);
  1119. KernelLog.String(" snduna="); KernelLog.Int(p.snduna-p.iss, 1);
  1120. KernelLog.String(" sndnxt="); KernelLog.Int(p.sndnxt-p.iss, 1);
  1121. KernelLog.String(" sndmax="); KernelLog.Int(p.sndmax-p.iss, 1);
  1122. KernelLog.String(" sndup="); KernelLog.Int(p.sndup-p.iss, 1);
  1123. KernelLog.String(" sndwl2="); KernelLog.Int(p.sndwl2-p.iss, 1);
  1124. KernelLog.String(" rtseq="); KernelLog.Int(p.rtseq-p.iss, 1);
  1125. KernelLog.Ln;
  1126. KernelLog.String(" sndwnd="); KernelLog.Int(p.sndwnd, 1);
  1127. KernelLog.String(" sndcwnd="); KernelLog.Int(p.sndcwnd, 1);
  1128. KernelLog.String(" sndcc="); KernelLog.Int(p.sndcc, 1);
  1129. KernelLog.String(" sndspace="); KernelLog.Int(p.sndspace, 1);
  1130. KernelLog.String(" sndssthresh="); KernelLog.Int(p.sndssthresh, 1);
  1131. KernelLog.Ln;
  1132. KernelLog.String(" irs="); KernelLog.Int(p.irs, 1);
  1133. KernelLog.String(" rcvnxt="); KernelLog.Int(p.rcvnxt-p.irs, 1);
  1134. KernelLog.String(" rcvup="); KernelLog.Int(p.rcvup-p.irs, 1);
  1135. KernelLog.String(" sndwl1="); KernelLog.Int(p.sndwl1-p.irs, 1);
  1136. KernelLog.String(" rcvadv="); KernelLog.Int(p.rcvadv-p.irs, 1);
  1137. KernelLog.String(" lastacksent="); KernelLog.Int(p.lastacksent-p.irs, 1);
  1138. KernelLog.Ln;
  1139. KernelLog.String(" rcvwnd="); KernelLog.Int(p.rcvwnd, 1);
  1140. KernelLog.String(" rcvspace="); KernelLog.Int(p.rcvspace, 1);
  1141. KernelLog.String(" rcvhiwat="); KernelLog.Int(p.rcvhiwat, 1);
  1142. KernelLog.String(" idle="); KernelLog.Int(p.idle, 1);
  1143. KernelLog.String(" rtt="); KernelLog.Int(p.rtt, 1);
  1144. KernelLog.String(" srtt="); KernelLog.Int(p.srtt, 1);
  1145. KernelLog.Ln;
  1146. KernelLog.String(" rttvar="); KernelLog.Int(p.rttvar, 1);
  1147. KernelLog.String(" rttmin="); KernelLog.Int(p.rttmin, 1);
  1148. KernelLog.String(" maxsndwnd="); KernelLog.Int(p.maxsndwnd, 1);
  1149. KernelLog.String(" sndscale="); KernelLog.Int(p.sndscale, 1);
  1150. KernelLog.String(" rcvscale="); KernelLog.Int(p.rcvscale, 1);
  1151. KernelLog.String(" requestrscale="); KernelLog.Int(p.requestrscale, 1);
  1152. KernelLog.Ln;
  1153. KernelLog.String(" requestedsscale="); KernelLog.Int(p.requestedsscale, 1);
  1154. KernelLog.String(" tsrecent="); KernelLog.Int(p.tsrecent, 1);
  1155. KernelLog.String(" tsrecentage="); KernelLog.Int(p.tsrecentage, 1);
  1156. KernelLog.String(" rxtshift="); KernelLog.Int(p.rxtshift, 1);
  1157. KernelLog.String(" rxtcur="); KernelLog.Int(p.rxtcur, 1);
  1158. KernelLog.String(" dupacks="); KernelLog.Int(p.dupacks, 1);
  1159. KernelLog.Ln; KernelLog.Ln
  1160. END
  1161. END TraceConnection;
  1162. (* Trace the protocol. *)
  1163. PROCEDURE TraceTCP(msg: ARRAY OF CHAR; p: Connection; CONST hdr, data: ARRAY OF CHAR; hlen, ofs, len: LONGINT);
  1164. BEGIN
  1165. IF Trace THEN
  1166. WriteTime(Kernel.GetTicks()); KernelLog.Char(" ");
  1167. KernelLog.String(msg); TraceConnection(p);
  1168. IF TracePacket THEN
  1169. KernelLog.Memory(ADDRESSOF(hdr[0]), hlen);
  1170. KernelLog.Memory(ADDRESSOF(data[ofs]), len)
  1171. END
  1172. END
  1173. END TraceTCP;
  1174. (* Output a TCP segment. *)
  1175. PROCEDURE Output(p: Connection);
  1176. VAR
  1177. idle, sendalot: BOOLEAN;
  1178. optLen, off, sum, win, len, adv, x, startseq, left: LONGINT;
  1179. pf: SET; buf: SendBuffer; data: SendData;
  1180. pseudoHdr: ARRAY MaxPseudoHdrLen OF CHAR;
  1181. hdr: ARRAY MaxTCPHdrLen OF CHAR;
  1182. pseudoHdrLen: LONGINT;
  1183. BEGIN
  1184. idle := (p.sndmax = p.snduna);
  1185. IF idle & (p.idle >= p.rxtcur) THEN p.sndcwnd := p.maxseg END;
  1186. REPEAT
  1187. sendalot := FALSE;
  1188. LOOP (* look for reason to send a segment (not a real loop, just a goto-substitute) *)
  1189. off := p.sndnxt - p.snduna; (* the first off bytes from the buffer have been sent and are waiting for Ack *)
  1190. win := p.sndwnd; (* minimum of window advertised by receiver and the congestion window *)
  1191. IF HandleCongestion & (p.sndcwnd < win) THEN win := p.sndcwnd END;
  1192. pf := outflags[p.state];
  1193. IF Force IN p.flags THEN
  1194. IF win = 0 THEN
  1195. IF off < p.sndcc THEN EXCL(pf, Fin) END;
  1196. win := 1
  1197. ELSE
  1198. p.timer[Persist] := 0; p.rxtshift := 0
  1199. END
  1200. END;
  1201. len := p.sndcc; (* minimum of bytes in send buffer and win *)
  1202. IF win < len THEN len := win END;
  1203. DEC(len, off); (* off bytes have already been sent and are waiting for Ack *)
  1204. IF len < 0 THEN
  1205. len := 0;
  1206. IF win = 0 THEN p.timer[ReXmt] := 0; p.sndnxt := p.snduna END;
  1207. END;
  1208. IF len > p.maxseg THEN len := p.maxseg; sendalot := TRUE END;
  1209. IF (p.sndnxt + len) - (p.snduna + p.sndcc) < 0 THEN EXCL(pf, Fin) END; (* not emptying send buffer *)
  1210. win := p.rcvspace; (* now win is receive window advertised *)
  1211. IF len # 0 THEN
  1212. IF len = p.maxseg THEN EXIT END;
  1213. IF (idle OR (NoDelay IN p.flags)) & (len + off >= p.sndcc) THEN EXIT END;
  1214. IF Force IN p.flags THEN EXIT END;
  1215. IF len >= p.maxsndwnd DIV 2 THEN EXIT END;
  1216. IF p.sndnxt - p.sndmax < 0 THEN EXIT END
  1217. END;
  1218. IF win > 0 THEN
  1219. adv := ASH(MaxWin, p.rcvscale);
  1220. IF win < adv THEN adv := win END;
  1221. DEC(adv, p.rcvadv - p.rcvnxt);
  1222. IF adv >= 2*p.maxseg THEN EXIT END;
  1223. IF 2*adv >= p.rcvhiwat THEN EXIT END
  1224. END;
  1225. IF AckNow IN p.flags THEN EXIT END;
  1226. IF pf * {Syn,Rst} # {} THEN EXIT END;
  1227. IF p.sndup - p.snduna > 0 THEN EXIT END;
  1228. IF (Fin IN pf) & (~(SentFin IN p.flags) OR (p.sndnxt = p.snduna)) THEN EXIT END;
  1229. IF (p.sndcc # 0) & (p.timer[ReXmt] = 0) & (p.timer[Persist] = 0) THEN
  1230. p.rxtshift := 0; SetPersist(p)
  1231. END;
  1232. RETURN (* 0 *) (* no reason to send a segment *)
  1233. END; (* LOOP *)
  1234. (* form output segment *)
  1235. optLen := 0;
  1236. IF Syn IN pf THEN
  1237. p.sndnxt := p.iss;
  1238. IF GenOptions THEN
  1239. (* generate MSS option *)
  1240. hdr[MinTCPHdrLen+optLen] := 2X; (* MSS option *)
  1241. hdr[MinTCPHdrLen+optLen+1] := 4X; (* option length *)
  1242. Network.PutNet2(hdr, MinTCPHdrLen+optLen+2, p.int.dev.mtu-120); (* MSS = dev.mtu-120 *)
  1243. INC(optLen, 4);
  1244. (* generate window scale option *)
  1245. IF ((ReqScale IN p.flags) & (~(Ack IN pf) OR (RcvdScale IN p.flags))) THEN
  1246. hdr[MinTCPHdrLen+optLen] := 1X; (* NOP *)
  1247. hdr[MinTCPHdrLen+optLen+1] := 3X; (* window scale option *)
  1248. hdr[MinTCPHdrLen+optLen+2] := 3X; (* option length *)
  1249. hdr[MinTCPHdrLen+optLen+3] := CHR(p.requestrscale); (* window scale *)
  1250. INC(optLen, 4);
  1251. END;
  1252. END;
  1253. END;
  1254. (* generate timestamp option *)
  1255. IF GenOptions & DoRFC1323 & (ReqTstmp IN p.flags) & ~(Rst IN pf) & ((pf * {Syn, Ack} = {Syn}) OR (RcvdTstmp IN p.flags)) THEN
  1256. hdr[MinTCPHdrLen+optLen] := 1X; (* NOP *)
  1257. hdr[MinTCPHdrLen+optLen+1] := 1X; (* NOP *)
  1258. hdr[MinTCPHdrLen+optLen+2] := 8X; (* timestamp option *)
  1259. hdr[MinTCPHdrLen+optLen+3] := 0AX; (* option length *)
  1260. Network.PutNet4(hdr, MinTCPHdrLen+optLen+4, timeSource.now);
  1261. Network.PutNet4(hdr, MinTCPHdrLen+optLen+8, p.tsrecent);
  1262. INC(optLen, 12);
  1263. END;
  1264. (* This doesn't work if Fin was set before !! (bug in TCP/IP Illustrated Vol. 2, p. 873, fig. 26.24)
  1265. Solved by setting MSS = 536 - 12 (size of timestamp option) and commenting this out.
  1266. (mvt, 28.02.2004)
  1267. IF len > p.maxseg - optLen THEN
  1268. len := p.maxseg - optLen;
  1269. sendalot := TRUE;
  1270. END;
  1271. *)
  1272. IF len # 0 THEN
  1273. IF (Force IN p.flags) & (len = 1) THEN Machine.AtomicInc(NTCPSendProbe)
  1274. ELSIF p.sndnxt - p.sndmax < 0 THEN Machine.AtomicInc(NTCPReXmtPack); Machine.AtomicAdd(NTCPReXmtByte, len)
  1275. ELSE Machine.AtomicInc(NTCPSendPack); Machine.AtomicAdd(NTCPSendByte, len)
  1276. END;
  1277. IF off + len = p.sndcc THEN INCL(pf, Psh) END;
  1278. (* data to send is in buffer[off..off+len-1] *)
  1279. buf := p.sndhead; WHILE off >= buf.len DO DEC(off, buf.len); buf := buf.next END;
  1280. IF off+len <= buf.len THEN (* all data is this buffer *)
  1281. data := buf.data; INC(off, buf.ofs)
  1282. ELSE (* data is spread over more buffers *)
  1283. Machine.AtomicInc(NTCPSplitBuffer);
  1284. data := p.sndcontig;
  1285. ASSERT(len <= LEN(data^));
  1286. ASSERT(buf.len-off <= len); (* index check *)
  1287. IF SystemMove THEN
  1288. SYSTEM.MOVE(ADDRESSOF(buf.data[off+buf.ofs]), ADDRESSOF(data[0]), buf.len-off)
  1289. ELSE
  1290. Network.Copy(buf.data^, data^, off+buf.ofs, 0, buf.len-off)
  1291. END;
  1292. off := buf.len-off; left := len-off;
  1293. WHILE left # 0 DO
  1294. buf := buf.next; IF left <= buf.len THEN x := left ELSE x := buf.len END;
  1295. ASSERT(off+x <= len); (* index check *)
  1296. IF SystemMove THEN
  1297. SYSTEM.MOVE(ADDRESSOF(buf.data[buf.ofs]), ADDRESSOF(data[off]), x)
  1298. ELSE
  1299. Network.Copy(buf.data^, data^, buf.ofs, off, x)
  1300. END;
  1301. INC(off, x); DEC(left, x)
  1302. END;
  1303. off := 0
  1304. END
  1305. ELSE
  1306. IF AckNow IN p.flags THEN Machine.AtomicInc(NTCPAcks)
  1307. ELSIF pf * {Syn,Fin,Rst} # {} THEN Machine.AtomicInc(NTCPSendCtrl)
  1308. ELSIF p.sndup - p.snduna > 0 THEN Machine.AtomicInc(NTCPSendUrg)
  1309. ELSE Machine.AtomicInc(NTCPSendWinUp)
  1310. END;
  1311. data := empty; off := 0
  1312. END;
  1313. IF (Fin IN pf) & (SentFin IN p.flags) & (p.sndnxt = p.sndmax) THEN DEC(p.sndnxt) END;
  1314. IF (len # 0) OR (pf * {Syn,Fin} # {}) OR (p.timer[Persist] # 0) THEN
  1315. Network.PutNet4(hdr, 4, p.sndnxt) (* sequence number *)
  1316. ELSE
  1317. Network.PutNet4(hdr, 4, p.sndmax)
  1318. END;
  1319. Network.PutNet4(hdr, 8, p.rcvnxt); (* acknowledgement number *)
  1320. IF (win < p.rcvhiwat DIV 4) & (win < p.maxseg) THEN win := 0 END;
  1321. IF win > ASH(MaxWin, p.rcvscale) THEN win := ASH(MaxWin, p.rcvscale) END;
  1322. IF win < p.rcvadv - p.rcvnxt THEN win := p.rcvadv - p.rcvnxt END;
  1323. Network.PutNet2(hdr, 14, ASH(win, -p.rcvscale));
  1324. IF p.sndup - p.sndnxt > 0 THEN
  1325. x := p.sndup - p.sndnxt;
  1326. IF x > 65535 THEN x := 65535 END;
  1327. Network.PutNet2(hdr, 18, x);
  1328. INCL(pf, Urg)
  1329. ELSE
  1330. p.sndup := p.snduna
  1331. END;
  1332. hdr[13] := CHR(SHORT(SHORT(SYSTEM.VAL(LONGINT, pf))));
  1333. (* set rest of TCP header *)
  1334. Network.PutNet2(hdr, 0, p.lport);
  1335. Network.PutNet2(hdr, 2, p.fport);
  1336. hdr[12] := CHR((MinTCPHdrLen+optLen) DIV 4*10H);
  1337. Network.Put2(hdr, 16, 0); (* checksum := 0; *)
  1338. IF ~(Network.ChecksumTCP IN p.int.dev.calcChecksum) THEN
  1339. (* set pseudo header *)
  1340. pseudoHdrLen := p.int.WritePseudoHeader(pseudoHdr, p.int.localAdr, p.fip, IPTypeTCP, MinTCPHdrLen+optLen+len);
  1341. sum := IP.Checksum1(pseudoHdr, 0, pseudoHdrLen, 0);
  1342. sum := IP.Checksum1(hdr, 0, MinTCPHdrLen+optLen, sum);
  1343. sum := IP.Checksum2(data^, off, len, sum);
  1344. Network.Put2(hdr, 16, sum); (* checksum := sum *)
  1345. END;
  1346. IF ~(Force IN p.flags) OR (p.timer[Persist] = 0) THEN
  1347. startseq := p.sndnxt;
  1348. IF pf * {Syn,Fin} # {} THEN
  1349. IF Syn IN pf THEN INC(p.sndnxt) END;
  1350. IF Fin IN pf THEN INC(p.sndnxt); INCL(p.flags, SentFin) END
  1351. END;
  1352. INC(p.sndnxt, len);
  1353. IF p.sndnxt - p.sndmax > 0 THEN
  1354. p.sndmax := p.sndnxt;
  1355. IF p.rtt = 0 THEN p.rtt := 1; p.rtseq := startseq; Machine.AtomicInc(NTCPSegsTimed) END
  1356. END;
  1357. IF (p.timer[ReXmt] = 0) & (p.sndnxt # p.snduna) THEN
  1358. p.timer[ReXmt] := p.rxtcur;
  1359. IF p.timer[Persist] # 0 THEN p.timer[Persist] := 0; p.rxtshift := 0 END
  1360. END
  1361. ELSIF (p.sndnxt + len) - p.sndmax > 0 THEN
  1362. p.sndmax := p.sndnxt + len
  1363. ELSE (* skip *)
  1364. END;
  1365. IF TraceProtocol THEN
  1366. TraceTCP("Output", p, hdr, data^, MinTCPHdrLen+optLen, off, len)
  1367. END;
  1368. (* Send packet *)
  1369. p.int.Send(IPTypeTCP, p.fip, hdr, data^, MinTCPHdrLen+optLen, off, len, IP.MaxTTL);
  1370. (* old code:
  1371. IP.IPOutput(IP.default, p.hdr, data^, IP.MinIPHdrLen+MinTCPHdrLen, off, len);
  1372. IF FALSE THEN (* error in IPOutput *)
  1373. IF FALSE THEN (* out of buffers *)
  1374. p.sndcwnd := p.maxseg; (* close congestion window *)
  1375. RETURN (* 0 *)
  1376. END;
  1377. IF FALSE & (p.state >= SynReceived) THEN (* host unreachable or network down *)
  1378. (*p.softerror := error;*) RETURN (* 0 *)
  1379. END;
  1380. RETURN (* error *)
  1381. END;
  1382. *)
  1383. Machine.AtomicInc(NTCPSendTotal);
  1384. IF (win > 0) & ((p.rcvnxt + win) - p.rcvadv > 0) THEN p.rcvadv := p.rcvnxt + win END;
  1385. p.lastacksent := p.rcvnxt;
  1386. p.flags := p.flags - {AckNow,DelAck}
  1387. UNTIL ~sendalot;
  1388. (* RETURN 0 *)
  1389. END Output;
  1390. (* Special output function for Rst and KeepAlive packets (fig. 26.34). *)
  1391. PROCEDURE Respond(p: Connection; ack, seq: LONGINT; rf: SET);
  1392. VAR
  1393. win, sum: LONGINT;
  1394. pseudoHdr: ARRAY MaxPseudoHdrLen OF CHAR;
  1395. hdr: ARRAY MaxTCPHdrLen OF CHAR;
  1396. pseudoHdrLen: LONGINT;
  1397. BEGIN
  1398. win := ASH(p.rcvspace, -p.rcvscale); (* zero in nilpcb *)
  1399. IF rf = {} THEN
  1400. (* keepalive probe *)
  1401. INCL(rf, Ack)
  1402. ELSE
  1403. (* Rst segment *)
  1404. END;
  1405. (* set TCP header *)
  1406. Network.PutNet2(hdr, 0, p.lport);
  1407. Network.PutNet2(hdr, 2, p.fport);
  1408. Network.PutNet4(hdr, 4, seq);
  1409. Network.PutNet4(hdr, 8, ack);
  1410. hdr[12] := CHR(MinTCPHdrLen DIV 4*10H);
  1411. hdr[13] := CHR(SHORT(SHORT(SYSTEM.VAL(LONGINT, rf))));
  1412. Network.PutNet2(hdr, 14, win);
  1413. Network.Put2(hdr, 16, 0); (* checksum := 0 *)
  1414. Network.Put2(hdr, 18, 0); (* urgent pointer := 0 *)
  1415. IF ~(Network.ChecksumTCP IN p.int.dev.calcChecksum) THEN
  1416. (* set pseudo header *)
  1417. pseudoHdrLen := p.int.WritePseudoHeader(pseudoHdr, p.int.localAdr, p.fip, IPTypeTCP, MinTCPHdrLen);
  1418. sum := IP.Checksum1(pseudoHdr, 0, pseudoHdrLen, 0);
  1419. sum := IP.Checksum2(hdr, 0, MinTCPHdrLen, sum);
  1420. Network.Put2(hdr, 16, sum); (* checksum := sum; *)
  1421. END;
  1422. p.int.Send(IPTypeTCP, p.fip, hdr, hdr, MinTCPHdrLen, 0, 0, IP.MaxTTL);
  1423. END Respond;
  1424. (* Cancel all timers. *)
  1425. PROCEDURE CancelTimers(p: Connection);
  1426. VAR i: LONGINT;
  1427. BEGIN
  1428. FOR i := 0 TO NumTimers-1 DO p.timer[i] := 0 END
  1429. END CancelTimers;
  1430. (* Apply new RTT measurement to smoothed estimators. *)
  1431. (*
  1432. PROCEDURE XmitTimer(p: Connection; rtt: LONGINT);
  1433. VAR delta: LONGINT;
  1434. BEGIN
  1435. Machine.AtomicInc(NTCPRTTUpdated);
  1436. IF p.srtt # 0 THEN
  1437. delta := rtt - 1 - ASH(p.srtt, -RTTShift);
  1438. INC(p.srtt, delta);
  1439. IF p.srtt <= 0 THEN p.srtt := 1 END;
  1440. IF delta < 0 THEN delta := -delta END;
  1441. DEC(delta, ASH(p.rttvar, -RTTVarShift));
  1442. INC(p.rttvar, delta);
  1443. IF p.rttvar <= 0 THEN p.rttvar := 1 END
  1444. ELSE
  1445. p.srtt := ASH(rtt, RTTShift); p.rttvar := ASH(rtt, RTTVarShift-1)
  1446. END;
  1447. p.rtt := 0; p.rxtshift := 0;
  1448. RangeSet(p.rxtcur, ASH(p.srtt, -RTTShift) + p.rttvar, p.rttmin, ReXmtMax);
  1449. (*p.softerror := 0*)
  1450. END XmitTimer;
  1451. *)
  1452. PROCEDURE XmitTimer(p: Connection; rtt: LONGINT);
  1453. (*
  1454. m -> rtt
  1455. sa -> p.srtt
  1456. sd -> p.rttvar
  1457. *)
  1458. VAR delta: LONGINT;
  1459. BEGIN
  1460. Machine.AtomicInc(NTCPRTTUpdated);
  1461. IF p.srtt # 0 THEN
  1462. (* delta := (rtt*4) - ASH(p.srtt, -RTTShift);*)
  1463. delta := rtt - 1 - ASH(p.srtt, -RTTShift);
  1464. INC(p.srtt, delta);
  1465. IF p.srtt <= 0 THEN p.srtt := 1 END;
  1466. IF delta < 0 THEN delta := -delta END;
  1467. DEC(delta, ASH(p.rttvar, -RTTVarShift));
  1468. INC(p.rttvar, delta);
  1469. IF p.rttvar <= 0 THEN p.rttvar := 1 END
  1470. ELSE
  1471. p.srtt := ASH(rtt, RTTShift); p.rttvar := ASH(rtt, RTTVarShift-1)
  1472. END;
  1473. p.rtt := 0; p.rxtshift := 0;
  1474. (* p.rxtcur:=((p.srtt DIV 8)+ p.rttvar) DIV 4;
  1475. IF p.rxtcur < (rtt+2) THEN p.rxtcur:=rtt; END;*)
  1476. RangeSet(p.rxtcur, ASH(p.srtt, -RTTShift) + p.rttvar, MinTime, ReXmtMax);
  1477. (*p.softerror := 0*)
  1478. END XmitTimer;
  1479. (* Drop len bytes from the front of the send buffer. *)
  1480. PROCEDURE SbDrop(p: Connection; len: LONGINT);
  1481. VAR buf: SendBuffer;
  1482. BEGIN
  1483. DEC(p.sndcc, len); INC(p.sndspace, len);
  1484. buf := p.sndhead;
  1485. LOOP
  1486. IF buf.len > len THEN (* part of buffer will remain *)
  1487. INC(buf.ofs, len); DEC(buf.len, len); (* ignore buf.seq (later: why?) *)
  1488. EXIT
  1489. END;
  1490. DEC(len, buf.len);
  1491. buf.ofs := 0; buf.len := 0; (* make buffer ready for re-use *)
  1492. IF buf # p.sndtail THEN buf := buf.next END;
  1493. IF len = 0 THEN EXIT END
  1494. END;
  1495. p.sndhead := buf
  1496. END SbDrop;
  1497. (* Close a connection (fig. 27.4-6). *)
  1498. PROCEDURE CloseConnection(p: Connection);
  1499. VAR
  1500. buf: Network.Buffer;
  1501. BEGIN
  1502. IF FALSE (* we sent enough data to update rtt in route *) THEN
  1503. END;
  1504. pool.Remove(p);
  1505. (* can not remove from parent's accept list, because of possible deadlock *)
  1506. IF p = lastpcb THEN lastpcb := nilpcb END; (* only for GC -- race does not matter *)
  1507. (* can not clear any pcb pointer fields, because Lookup is non-exclusive *)
  1508. (*SoIsDisconnected(p);*)
  1509. p.state := Closed;
  1510. (* return the buffers still in receive queue *)
  1511. p.rcvreasm := NIL;
  1512. p.rcvtail := NIL;
  1513. WHILE p.rcvhead # NIL DO
  1514. buf := p.rcvhead;
  1515. p.rcvhead := p.rcvhead.next;
  1516. Network.ReturnBuffer(buf);
  1517. END;
  1518. Machine.AtomicInc(NTCPClosed);
  1519. END CloseConnection;
  1520. (* Drop a connection (fig. 27.2). *)
  1521. PROCEDURE Drop(p: Connection; err: LONGINT);
  1522. BEGIN
  1523. IF p.state >= SynReceived THEN
  1524. p.state := Closed; Output(p); Machine.AtomicInc(NTCPDrops)
  1525. ELSE
  1526. Machine.AtomicInc(NTCPConnDrops)
  1527. END;
  1528. (* IF (err = TimedOut) & (p.softerror # Ok) THEN err := p.softerror END; *)
  1529. p.error := err; CloseConnection(p)
  1530. END Drop;
  1531. PROCEDURE SetMSS(p: Connection; mss: LONGINT);
  1532. (* Error(NIYMSS, 0, p); *)
  1533. (* Processing of received MSS option not necessary as long as sending is always done with MSS=536. *)
  1534. END SetMSS;
  1535. (* Process a received TCP segment. *)
  1536. PROCEDURE Input(int: IP.Interface; type: LONGINT; fip, lip: IP.Adr; buffer: Network.Buffer);
  1537. VAR
  1538. lport, fport, hdrLen: LONGINT;
  1539. p: Connection;
  1540. BEGIN
  1541. ASSERT(type = IPTypeTCP);
  1542. Machine.AtomicInc(NTCPRcvTotal);
  1543. IF IP.AdrsEqual(int.localAdr, lip) THEN
  1544. IF buffer.len >= MinTCPHdrLen THEN
  1545. hdrLen := LONG(ORD(buffer.data[buffer.ofs+12])) DIV 10H * 4;
  1546. IF (hdrLen < MinTCPHdrLen) OR (hdrLen > buffer.len) THEN
  1547. (* bad header length *)
  1548. Error(BadHeaderLength, hdrLen, NIL);
  1549. (*GotoDrop;*)
  1550. ELSE
  1551. (* findpcb *)
  1552. p := lastpcb;
  1553. fport := Network.GetNet2(buffer.data, buffer.ofs);
  1554. lport := Network.GetNet2(buffer.data, buffer.ofs+2);
  1555. IF (p = nilpcb) OR (~IP.AdrsEqual(p.fip, fip)) OR (p.lport # lport) OR (p.fport # fport) THEN
  1556. p := pool.Lookup(lport, fport, fip);
  1557. IF p = nilpcb THEN
  1558. (* look for listening connection *)
  1559. p := pool.Lookup(lport, NilPort, IP.NilAdr);
  1560. END;
  1561. lastpcb := p;
  1562. Machine.AtomicInc(NTCPCacheMiss);
  1563. END;
  1564. p.Input(int, fip, hdrLen, buffer);
  1565. RETURN; (* w/o returning buffer *)
  1566. END;
  1567. ELSE
  1568. Error(SegmentTooSmall, buffer.len, NIL);
  1569. END;
  1570. ELSE
  1571. Error(BroadcastReceived, buffer.len, NIL);
  1572. END;
  1573. Network.ReturnBuffer(buffer);
  1574. END Input;
  1575. (* Process a received TCP segment for the specified Connection. *)
  1576. PROCEDURE ProcessInput(p: Connection; hdrLen: LONGINT; buffer: Network.Buffer; drop: BOOLEAN; VAR bufferQueued: BOOLEAN);
  1577. CONST
  1578. Options = 0; TSPresent = 1; NeedOutput = 2;
  1579. VAR
  1580. win, sum, urp, seq, ack, tsval, tsecr, acked, discard, tlen, optLen: LONGINT;
  1581. pseudoHdr: ARRAY MaxPseudoHdrLen OF CHAR;
  1582. pseudoHdrLen: LONGINT;
  1583. pf, lf: SET;
  1584. reassembledLength: LONGINT;
  1585. fragmentBuffer: Network.Buffer;
  1586. PROCEDURE GotoDrop; (* fig. 29.27 *)
  1587. BEGIN
  1588. IF TraceProtocol THEN TraceTCP("Drop", p, empty^, empty^, 0, 0, 0) END;
  1589. IF drop THEN Drop(p, ConnectionAborted) END
  1590. END GotoDrop;
  1591. PROCEDURE GotoDropReset; (* fig. 29.27 - may be called with p = nilpcb (at start) *)
  1592. BEGIN
  1593. IF (Rst IN pf) THEN
  1594. GotoDrop
  1595. ELSE
  1596. IF Ack IN pf THEN
  1597. Respond(p, 0, ack, {Rst})
  1598. ELSE
  1599. IF Syn IN pf THEN INC(tlen) END;
  1600. Respond(p, seq + tlen, 0, {Rst,Ack})
  1601. END;
  1602. IF drop THEN Drop(p, ConnectionAborted) END
  1603. END
  1604. END GotoDropReset;
  1605. PROCEDURE GotoDropAfterAck; (* fig. 29.26 *)
  1606. BEGIN
  1607. IF Rst IN pf THEN
  1608. GotoDrop
  1609. ELSE
  1610. INCL(p.flags, AckNow); Output(p)
  1611. END
  1612. END GotoDropAfterAck;
  1613. PROCEDURE ProcessOptions; (* fig. 28.9 & 28.10 *)
  1614. VAR opt: CHAR; i, m, optlen: LONGINT;
  1615. BEGIN
  1616. i := buffer.ofs+MinTCPHdrLen; m := buffer.ofs+hdrLen;
  1617. LOOP
  1618. IF i >= m THEN EXIT END;
  1619. opt := buffer.data[i];
  1620. IF opt = 0X THEN
  1621. EXIT; (* EOL *)
  1622. ELSIF opt = 1X THEN
  1623. optlen := 1; (* NOP *)
  1624. ELSE
  1625. optlen := ORD(buffer.data[i+1]);
  1626. IF optlen = 0 THEN EXIT END;
  1627. END;
  1628. CASE opt OF
  1629. 2X: (* MaxSeg *)
  1630. IF (optlen = 4) & (Syn IN pf) THEN
  1631. SetMSS(p, Network.GetNet2(buffer.data, i+2));
  1632. END;
  1633. |3X: (* Window Scaling *)
  1634. IF (optlen = 3) & (Syn IN pf) THEN
  1635. INCL(p.flags, RcvdScale);
  1636. p.requestedsscale := MIN(LONG(ORD(buffer.data[i+2])), MaxWinShift);
  1637. END;
  1638. |8X: (* Timestamp *)
  1639. IF DoRFC1323 & (optlen = 10) THEN
  1640. INCL(lf, TSPresent);
  1641. tsval := Network.GetNet4(buffer.data, i+2);
  1642. tsecr := Network.GetNet4(buffer.data, i+6);
  1643. IF Syn IN pf THEN
  1644. INCL(p.flags, RcvdTstmp);
  1645. p.tsrecent := tsval;
  1646. p.tsrecentage := timeSource.now;
  1647. END;
  1648. END;
  1649. ELSE
  1650. (* skip *)
  1651. END;
  1652. INC(i, optlen);
  1653. END
  1654. END ProcessOptions;
  1655. PROCEDURE ProcessListen(): BOOLEAN; (* fig. 28.15-17 *)
  1656. VAR
  1657. res: WORD;
  1658. q: Connection;
  1659. BEGIN
  1660. IF Rst IN pf THEN GotoDrop; RETURN FALSE END;
  1661. IF Ack IN pf THEN GotoDropReset; RETURN FALSE END;
  1662. IF ~(Syn IN pf) THEN GotoDrop; RETURN FALSE END;
  1663. pool.Add(p, Network.GetNet2(buffer.data, buffer.ofs+2), Network.GetNet2(buffer.data, buffer.ofs), res);
  1664. IF res # Ok THEN
  1665. GotoDrop;
  1666. RETURN FALSE;
  1667. END;
  1668. IF ProcOptions & (Options IN lf) THEN ProcessOptions END;
  1669. p.iss := issSource.Get();
  1670. p.snduna := p.iss; p.sndnxt := p.iss; p.sndmax := p.iss; p.sndup := p.iss;
  1671. p.irs := seq; p.rcvnxt := seq+1; p.rcvadv := p.rcvnxt;
  1672. INCL(p.flags, AckNow);
  1673. p.state := SynReceived;
  1674. p.timer[Keep] := KeepInit;
  1675. drop := FALSE; (* commit *)
  1676. (* put on accept queue *)
  1677. ASSERT(Objects.LockedByCurrent(p.parent)); (* came here via Connection.Input of parent *)
  1678. q := p.parent.acceptNext; p.acceptNext := NIL;
  1679. IF q = NIL THEN
  1680. p.parent.acceptNext := p
  1681. ELSE
  1682. WHILE q.acceptNext # NIL DO q := q.acceptNext END; (* find last entry in queue *)
  1683. q.acceptNext := p
  1684. END;
  1685. Machine.AtomicInc(NTCPAccepts);
  1686. RETURN TRUE
  1687. END ProcessListen;
  1688. PROCEDURE ProcessSynSent(): BOOLEAN;
  1689. BEGIN
  1690. IF (Ack IN pf) & ((ack - p.iss <= 0) OR (ack - p.sndmax > 0)) THEN GotoDropReset; RETURN FALSE END;
  1691. IF Rst IN pf THEN
  1692. IF Ack IN pf THEN Error(ConnectionRefused, 0, p); Drop(p, ConnectionRefused) END;
  1693. GotoDrop; RETURN FALSE
  1694. END;
  1695. IF ~(Syn IN pf) THEN GotoDrop; RETURN FALSE END;
  1696. IF Ack IN pf THEN
  1697. p.snduna := ack;
  1698. IF p.sndnxt - p.snduna < 0 THEN p.sndnxt := p.snduna END;
  1699. END;
  1700. p.timer[ReXmt] := 0;
  1701. p.irs := seq; p.rcvnxt := seq+1; p.rcvadv := p.rcvnxt;
  1702. INCL(p.flags, AckNow);
  1703. IF (Ack IN pf) & (p.snduna - p.iss > 0) THEN
  1704. Machine.AtomicInc(NTCPConnects); (*SoIsConnected(p);*)
  1705. p.state := Established;
  1706. IF p.flags * {RcvdScale,ReqScale} = {RcvdScale,ReqScale} THEN
  1707. p.sndscale := p.requestedsscale; p.rcvscale := p.requestrscale
  1708. END;
  1709. (*GotoPresent;*) (* not necessary, processed later *)
  1710. IF p.rtt # 0 THEN XmitTimer(p, p.rtt) END
  1711. ELSE
  1712. p.state := SynReceived
  1713. END;
  1714. RETURN TRUE
  1715. END ProcessSynSent;
  1716. PROCEDURE Trim1; (* fig. 28.21 *)
  1717. BEGIN
  1718. INC(seq);
  1719. IF tlen > p.rcvwnd THEN
  1720. Error(DataBeyondWindow1, tlen - p.rcvwnd, p); (* data received beyond window (with Syn) *)
  1721. tlen := p.rcvwnd; EXCL(pf, Fin)
  1722. END;
  1723. p.sndwl1 := seq-1; p.rcvup := seq
  1724. END Trim1;
  1725. PROCEDURE Paws(): BOOLEAN; (* fig. 28.22 *)
  1726. BEGIN
  1727. IF (TSPresent IN lf) & ~(Rst IN pf) & (p.tsrecent # 0) & (tsval - p.tsrecent < 0) THEN
  1728. IF (timeSource.now - p.tsrecentage) > PawsIdle THEN
  1729. p.tsrecent := 0
  1730. ELSE
  1731. Error(DuplicateSegmentPAWS, tlen, p); (* duplicate segment (PAWS) *)
  1732. GotoDropAfterAck; RETURN FALSE
  1733. END
  1734. END;
  1735. RETURN TRUE
  1736. END Paws;
  1737. PROCEDURE Trim2(todrop: LONGINT): BOOLEAN; (* fig. 28.24-25, corrected fig. 28.30*)
  1738. BEGIN
  1739. IF Syn IN pf THEN
  1740. EXCL(pf, Syn); INC(seq);
  1741. IF urp > 1 THEN DEC(urp) ELSE EXCL(pf, Urg) END;
  1742. DEC(todrop)
  1743. END;
  1744. IF (todrop > tlen) OR ((todrop = tlen) & ~(Fin IN pf)) THEN
  1745. EXCL(pf, Fin); INCL(p.flags, AckNow); todrop := tlen;
  1746. Error(DuplicateSegment, todrop, p) (* duplicate segment *)
  1747. ELSE
  1748. Error(DuplicatePartialSegment, todrop, p) (* partially duplicate segment *)
  1749. END;
  1750. INC(discard, todrop); INC(seq, todrop); DEC(tlen, todrop);
  1751. IF urp > todrop THEN DEC(urp, todrop) ELSE EXCL(pf, Urg); urp := 0 END;
  1752. RETURN TRUE
  1753. END Trim2;
  1754. PROCEDURE Trim3(todrop: LONGINT): BOOLEAN; (* fig. 28.29 *)
  1755. BEGIN
  1756. IF todrop >= tlen THEN
  1757. IF (Syn IN pf) & (p.state = TimeWait) & (seq - p.rcvnxt > 0) THEN
  1758. (*iss := p.rcvnxt + ISSInc; CloseConnection(p); goto findpcb*)
  1759. Error(NIYNewIncarnation, 0, p); (* new incarnation NIY - also read p. 945-946 *)
  1760. GotoDropAfterAck; RETURN FALSE
  1761. END;
  1762. IF (p.rcvwnd = 0) & (seq = p.rcvnxt) THEN
  1763. INCL(p.flags, AckNow); Machine.AtomicInc(NTCPRcvWinProbe)
  1764. ELSE
  1765. Error(DataBeyondWindow2, tlen, p); (* data received beyond window (complete) *)
  1766. GotoDropAfterAck; RETURN FALSE
  1767. END
  1768. ELSE
  1769. Error(DataBeyondWindow3, todrop, p) (* data received beyond window (partial) *)
  1770. END;
  1771. DEC(tlen, todrop); pf := pf - {Psh,Fin};
  1772. RETURN TRUE
  1773. END Trim3;
  1774. PROCEDURE RecordTS; (* fig. 28.35 *)
  1775. VAR x: LONGINT;
  1776. BEGIN
  1777. IF DoRFC1323 THEN
  1778. IF pf * {Syn,Fin} # {} THEN x := 1 ELSE x := 0 END;
  1779. IF p.lastacksent - (seq + tlen + x) < 0 THEN
  1780. p.tsrecentage := timeSource.now;
  1781. p.tsrecent := tsval;
  1782. END
  1783. END
  1784. END RecordTS;
  1785. PROCEDURE ProcessRst(): BOOLEAN; (* fig. 28.36 *)
  1786. BEGIN
  1787. CASE p.state OF
  1788. SynReceived, Established, FinWait1, FinWait2, CloseWait:
  1789. IF p.state = SynReceived THEN p.error := ConnectionRefused ELSE p.error := ConnectionReset END;
  1790. p.state := Closed; Error(p.error, 0, p); (* connection reset *)
  1791. CloseConnection(p); GotoDrop; RETURN FALSE
  1792. |Closing, LastAck:
  1793. CloseConnection(p); GotoDrop; RETURN FALSE
  1794. ELSE (* skip *)
  1795. END;
  1796. RETURN TRUE
  1797. END ProcessRst;
  1798. PROCEDURE ProcessAck(): BOOLEAN; (* fig. 29.2-29.14 *)
  1799. VAR onxt, cw, incr: LONGINT; finacked: BOOLEAN;
  1800. BEGIN
  1801. IF p.state IN {SynReceived..TimeWait} THEN
  1802. IF p.state = SynReceived THEN
  1803. IF (p.snduna - ack > 0) OR (ack - p.sndmax > 0) THEN
  1804. GotoDropReset; RETURN FALSE
  1805. END;
  1806. Machine.AtomicInc(NTCPConnects);
  1807. (*SoIsConnected(p);*)
  1808. p.state := Established;
  1809. IF p.flags * {RcvdScale,ReqScale} = {RcvdScale,ReqScale} THEN
  1810. p.sndscale := p.requestedsscale; p.rcvscale := p.requestrscale
  1811. END;
  1812. (* IF tlen > 0 THEN (* would inc of twice by the header size *)
  1813. Reasm;
  1814. END; *)
  1815. p.sndwl1 := seq-1;
  1816. END;
  1817. IF ack - p.snduna <= 0 THEN
  1818. IF (tlen = 0) & (win = p.sndwnd) THEN
  1819. Error(DuplicateAck, 0, p); (* duplicate ack *)
  1820. IF (p.timer[ReXmt] = 0) OR (ack # p.snduna) THEN
  1821. p.dupacks := 0
  1822. ELSE
  1823. INC(p.dupacks);
  1824. IF p.dupacks = ReXmtThresh THEN
  1825. onxt := p.sndnxt;
  1826. p.sndssthresh := MAX(MIN(p.sndwnd, p.sndcwnd) DIV 2 DIV p.maxseg, 2) * p.maxseg;
  1827. IF TraceCongestion THEN
  1828. KernelLog.String("DA sndssthresh := "); KernelLog.Int(p.sndssthresh, 1); KernelLog.Ln
  1829. END;
  1830. p.timer[ReXmt] := 0; p.rtt := 0; p.sndnxt := ack; p.sndcwnd := p.maxseg;
  1831. Output(p);
  1832. p.sndcwnd := p.sndssthresh + p.maxseg * p.dupacks;
  1833. IF onxt - p.sndnxt > 0 THEN p.sndnxt := onxt END;
  1834. GotoDrop; RETURN FALSE
  1835. ELSIF p.dupacks > ReXmtThresh THEN
  1836. INC(p.sndcwnd, p.maxseg);
  1837. Output(p);
  1838. GotoDrop; RETURN FALSE
  1839. ELSE (* skip *)
  1840. END
  1841. END
  1842. ELSE
  1843. p.dupacks := 0
  1844. END;
  1845. RETURN TRUE (* skip rest of Ack processing - goto step 6 *)
  1846. END;
  1847. IF (p.dupacks > ReXmtThresh) & (p.sndcwnd > p.sndssthresh) THEN
  1848. p.sndcwnd := p.sndssthresh
  1849. END;
  1850. p.dupacks := 0;
  1851. IF ack - p.sndmax > 0 THEN
  1852. Error(OutOfRangeAck, ack - p.sndmax, p); GotoDropAfterAck;
  1853. RETURN FALSE;
  1854. END;
  1855. acked := ack - p.snduna;
  1856. Machine.AtomicInc(NTCPAckPack); Machine.AtomicAdd(NTCPAckByte, acked);
  1857. IF TSPresent IN lf THEN XmitTimer(p, timeSource.now - tsecr + 1)
  1858. ELSIF (p.rtt # 0) & (ack - p.rtseq > 0) THEN XmitTimer(p, p.rtt)
  1859. ELSE (* skip *)
  1860. END;
  1861. IF ack = p.sndmax THEN p.timer[ReXmt] := 0; INCL(lf, NeedOutput)
  1862. ELSIF p.timer[Persist] = 0 THEN
  1863. p.timer[ReXmt] := p.rxtcur;
  1864. ELSE (* skip *)
  1865. END;
  1866. cw := p.sndcwnd; incr := p.maxseg;
  1867. IF cw > p.sndssthresh THEN incr := incr * incr DIV cw END;
  1868. p.sndcwnd := MIN(cw + incr, ASH(MaxWin, p.sndscale));
  1869. IF acked > p.sndcc THEN
  1870. DEC(p.sndwnd, p.sndcc); SbDrop(p, p.sndcc); finacked := TRUE
  1871. ELSE
  1872. SbDrop(p, acked); DEC(p.sndwnd, acked); finacked := FALSE
  1873. END;
  1874. (*IF Notify IN p.flags THEN SoWakeup(p) END;*)
  1875. p.snduna := ack;
  1876. IF p.sndnxt - p.snduna < 0 THEN p.sndnxt := p.snduna END;
  1877. CASE p.state OF
  1878. FinWait1:
  1879. IF finacked THEN
  1880. (*IF NoMore IN p.flags THEN SoIsDisconnected(p); p.timer[MSL2] := MaxIdle END;*)
  1881. p.timer[MSL2] := MaxIdle; (* otherwise we hang in FinWait2 *)
  1882. p.state := FinWait2
  1883. END
  1884. |Closing:
  1885. IF finacked THEN
  1886. p.state := TimeWait; CancelTimers(p); p.timer[MSL2] := 2 * MSL;
  1887. (*SoIsDisconnected(p)*)
  1888. END
  1889. |LastAck:
  1890. IF finacked THEN
  1891. CloseConnection(p); GotoDrop; RETURN FALSE
  1892. END
  1893. |TimeWait:
  1894. p.timer[MSL2] := 2 * MSL; GotoDropAfterAck; RETURN FALSE
  1895. ELSE (* skip *)
  1896. END (* CASE *)
  1897. END;
  1898. RETURN TRUE
  1899. END ProcessAck;
  1900. PROCEDURE GotoPresent;
  1901. VAR
  1902. buf: Network.Buffer;
  1903. BEGIN
  1904. buf := p.rcvreasm; (* first buffer on reassembly list *)
  1905. IF (p.state >= Established) & (buf # NIL) & (buf.int = p.rcvnxt) THEN
  1906. REPEAT
  1907. DEC(p.rcvspace, buf.len);
  1908. INC(p.rcvnxt, buf.len);
  1909. pf := buf.set * {Fin};
  1910. buf := buf.next;
  1911. UNTIL (buf = NIL) OR (buf.int # p.rcvnxt);
  1912. p.rcvreasm := buf;
  1913. ELSE
  1914. EXCL(pf, Fin);
  1915. END;
  1916. END GotoPresent;
  1917. PROCEDURE Reasm;
  1918. VAR
  1919. pos, last: Network.Buffer;
  1920. lap: LONGINT;
  1921. BEGIN
  1922. buffer.set := pf;
  1923. buffer.int := seq;
  1924. INC(buffer.ofs, hdrLen + discard);
  1925. buffer.len := tlen;
  1926. IF p.rcvhead = NIL THEN
  1927. (* insert into empty queue *)
  1928. buffer.next := NIL;
  1929. buffer.prev := NIL;
  1930. p.rcvhead := buffer;
  1931. p.rcvreasm := buffer;
  1932. p.rcvtail := buffer;
  1933. bufferQueued := TRUE;
  1934. ELSE
  1935. (* go to insert position, insert in front of pos and after last. *)
  1936. pos := p.rcvreasm;
  1937. IF pos = NIL THEN
  1938. (* no reasm part of queue *)
  1939. last := p.rcvtail;
  1940. ELSE
  1941. last := pos.prev;
  1942. WHILE (pos # NIL) & (pos.int < seq) DO
  1943. last := pos;
  1944. pos := pos.next;
  1945. END;
  1946. END;
  1947. IF last # NIL THEN
  1948. (* check for overlap with previous buffer *)
  1949. lap := (last.int + last.len) - seq;
  1950. IF lap > 0 THEN
  1951. (* some overlap - drop new data *)
  1952. IF lap >= tlen THEN
  1953. (* complete duplicate *)
  1954. Error(DataDuplicatePrevComplete, tlen, p);
  1955. RETURN;
  1956. ELSE
  1957. (* partial duplicate *)
  1958. Error(DataDuplicatePrevPartial, lap, p);
  1959. INC(buffer.ofs, lap);
  1960. DEC(buffer.len, lap);
  1961. DEC(tlen, lap);
  1962. INC(seq, lap);
  1963. buffer.int := seq;
  1964. END;
  1965. END;
  1966. END;
  1967. IF pos # NIL THEN
  1968. (* check for overlap with next buffer *)
  1969. lap := (seq + tlen) - pos.int;
  1970. IF lap > 0 THEN
  1971. (* some overlap - drop new data *)
  1972. IF lap >= tlen THEN
  1973. (* complete duplicate *)
  1974. Error(DataDuplicateNextComplete, lap, p);
  1975. RETURN;
  1976. ELSE
  1977. (* partial duplicate *)
  1978. Error(DataDuplicateNextPartial, lap, p);
  1979. DEC(tlen, lap);
  1980. DEC(buffer.len, lap);
  1981. END;
  1982. END;
  1983. END;
  1984. Machine.AtomicInc(NTCPRcvPackSlow);
  1985. Machine.AtomicAdd(NTCPRcvByteSlow, tlen);
  1986. (* insert buffer into correct position in queue *)
  1987. IF pos = NIL THEN
  1988. (* insert at the end of the queue *)
  1989. ASSERT(last = p.rcvtail);
  1990. buffer.next := NIL;
  1991. buffer.prev := last;
  1992. buffer.prev.next := buffer;
  1993. p.rcvtail := buffer;
  1994. IF p.rcvreasm = NIL THEN
  1995. p.rcvreasm := buffer;
  1996. END;
  1997. ELSIF last = NIL THEN
  1998. (* insert at the beginning of the queue *)
  1999. ASSERT((pos = p.rcvhead) & (pos = p.rcvreasm));
  2000. buffer.prev := NIL;
  2001. buffer.next := pos;
  2002. buffer.next.prev := buffer;
  2003. p.rcvhead := buffer;
  2004. p.rcvreasm := buffer;
  2005. ELSE
  2006. (* insert somewhere in the middle *)
  2007. ASSERT((last.next = pos) & (pos.prev = last));
  2008. last.next := buffer;
  2009. buffer.prev := last;
  2010. pos.prev := buffer;
  2011. buffer.next := pos;
  2012. IF buffer.next = p.rcvreasm THEN
  2013. p.rcvreasm := buffer;
  2014. END;
  2015. END;
  2016. bufferQueued := TRUE;
  2017. END;
  2018. GotoPresent;
  2019. END Reasm;
  2020. PROCEDURE DoData;
  2021. BEGIN
  2022. IF ((tlen # 0) OR (Fin IN pf)) & (p.state < TimeWait) THEN
  2023. IF (seq = p.rcvnxt) & (p.rcvreasm = NIL) & (p.state = Established) THEN
  2024. INCL(p.flags, DelAck)
  2025. ELSE
  2026. INCL(p.flags, AckNow) (* cf. fig. 27.15 *)
  2027. END;
  2028. Reasm();
  2029. ELSE
  2030. EXCL(pf, Fin)
  2031. END;
  2032. IF Fin IN pf THEN
  2033. IF p.state < TimeWait THEN
  2034. (*SoCantRcvMore(p);*)
  2035. INCL(p.flags, AckNow); INC(p.rcvnxt)
  2036. END;
  2037. CASE p.state OF
  2038. SynReceived, Established:
  2039. p.state := CloseWait
  2040. |FinWait1:
  2041. p.state := Closing
  2042. |FinWait2:
  2043. p.state := TimeWait; CancelTimers(p); p.timer[MSL2] := 2 * MSL;
  2044. (*SoIsDisconnected(p)*)
  2045. |TimeWait:
  2046. p.timer[MSL2] := 2 * MSL
  2047. ELSE (* skip *)
  2048. END (* CASE *)
  2049. END;
  2050. IF TraceProtocol THEN
  2051. TraceTCP("Input", p, buffer.data, empty^, buffer.ofs+hdrLen, 0, 0)
  2052. END;
  2053. IF (NeedOutput IN lf) OR (AckNow IN p.flags) THEN Output(p) END
  2054. END DoData;
  2055. PROCEDURE Step6(): BOOLEAN;
  2056. BEGIN
  2057. IF (Ack IN pf) & ((p.sndwl1 - seq < 0) OR ((p.sndwl1 = seq) & ((p.sndwl2 - ack < 0) OR
  2058. ((p.sndwl2 = ack) & (win > p.sndwnd))))) THEN
  2059. IF (tlen = 0) & (p.sndwl2 = ack) & (win > p.sndwnd) THEN Machine.AtomicInc(NTCPRcvWinUpd) END;
  2060. p.sndwnd := win; p.sndwl1 := seq; p.sndwl2 := ack;
  2061. IF p.sndwnd > p.maxsndwnd THEN p.maxsndwnd := p.sndwnd END;
  2062. INCL(lf, NeedOutput)
  2063. END;
  2064. IF (Urg IN pf) & (urp # 0) & (p.state < TimeWait) THEN
  2065. Error(NIYOutOfBand, 0, p); (* out-of-band data NIY *)
  2066. (*IF urp + p.rcvcc > sbmax THEN*)
  2067. urp := 0; EXCL(pf, Urg); DoData; RETURN FALSE;
  2068. (*END;*)
  2069. ELSE
  2070. IF p.rcvnxt - p.rcvup > 0 THEN p.rcvup := p.rcvnxt END
  2071. END;
  2072. RETURN TRUE
  2073. END Step6;
  2074. BEGIN
  2075. lf := {};
  2076. discard := 0; (* data from 0 to discard has to be thrown away. *)
  2077. tlen := buffer.len-hdrLen; (* length of user data. *)
  2078. optLen := hdrLen - MinTCPHdrLen; (* length of options *)
  2079. pf := SYSTEM.VAL(SET, LONG(ORD(buffer.data[buffer.ofs+13])));
  2080. IF optLen > 0 THEN (* TCP options present *)
  2081. Machine.AtomicInc(NTCPRcvOptions);
  2082. IF ProcOptions THEN
  2083. IF DoRFC1323 THEN
  2084. (* quick processing of timestamp option, fig. 28.4 *)
  2085. IF ((optLen = 12) OR ((optLen > 12) & (buffer.data[buffer.ofs+MinTCPHdrLen+12] = 0X))) & ~(Syn IN pf) &
  2086. (buffer.data[buffer.ofs+MinTCPHdrLen] = 1X) &
  2087. (buffer.data[buffer.ofs+MinTCPHdrLen+1] = 1X) &
  2088. (buffer.data[buffer.ofs+MinTCPHdrLen+2] = 8X) &
  2089. (buffer.data[buffer.ofs+MinTCPHdrLen+3] = 0AX) THEN
  2090. INCL(lf, TSPresent);
  2091. tsval := Network.GetNet4(buffer.data, buffer.ofs+MinTCPHdrLen+4);
  2092. tsecr := Network.GetNet4(buffer.data, buffer.ofs+MinTCPHdrLen+8);
  2093. ELSE
  2094. INCL(lf, Options);
  2095. END;
  2096. ELSE
  2097. INCL(lf, Options);
  2098. END
  2099. END
  2100. END;
  2101. (* initialize variables needed for GotoDropReset *)
  2102. seq := Network.GetNet4(buffer.data, buffer.ofs+4);
  2103. ack := Network.GetNet4(buffer.data, buffer.ofs+8);
  2104. (* pf := SYSTEM.VAL(SET, LONG(ORD(buffer.data[buffer.ofs+13])));*)
  2105. IF p = nilpcb THEN
  2106. IF packetDumpListener # NIL THEN packetDumpListener(p.fip, buffer) END;
  2107. GotoDropReset; RETURN
  2108. END;
  2109. IF p.state <= Closed THEN GotoDrop; RETURN END;
  2110. IF ~(Network.ChecksumTCP IN buffer.calcChecksum) THEN
  2111. (* calculate checksum *)
  2112. (* set pseudo header *)
  2113. reassembledLength := 0;
  2114. fragmentBuffer := buffer;
  2115. WHILE fragmentBuffer # NIL DO
  2116. INC(reassembledLength, fragmentBuffer.len);
  2117. fragmentBuffer := fragmentBuffer.nextFragment;
  2118. END;
  2119. pseudoHdrLen := p.int.WritePseudoHeader(pseudoHdr, p.fip, p.int.localAdr, IPTypeTCP, reassembledLength);
  2120. sum := IP.Checksum1(pseudoHdr, 0, pseudoHdrLen, 0);
  2121. IF buffer.nextFragment # NIL THEN
  2122. (* fragmented packets *)
  2123. fragmentBuffer := buffer;
  2124. WHILE fragmentBuffer.nextFragment # NIL DO
  2125. sum := IP.Checksum1(fragmentBuffer.data, fragmentBuffer.ofs, fragmentBuffer.len, sum);
  2126. fragmentBuffer := fragmentBuffer.nextFragment;
  2127. END;
  2128. sum := IP.Checksum2(fragmentBuffer.data, fragmentBuffer.ofs, fragmentBuffer.len, sum);
  2129. ELSE
  2130. sum := IP.Checksum2(buffer.data, buffer.ofs, buffer.len, sum);
  2131. END;
  2132. IF sum # 0 THEN
  2133. Error(BadChecksum, 0, p);
  2134. GotoDrop;
  2135. RETURN;
  2136. END;
  2137. END;
  2138. win := Network.GetNet2(buffer.data, buffer.ofs+14);
  2139. urp := Network.GetNet2(buffer.data, buffer.ofs+18);
  2140. IF ~(Syn IN pf) THEN win := ASH(win, p.sndscale) END;
  2141. p.idle := 0; p.timer[Keep] := KeepIdle;
  2142. IF ProcOptions & (Options IN lf) & (p.state # Listen) THEN ProcessOptions END;
  2143. (* header prediction (fig. 28.11-13) *)
  2144. IF (p.state = Established) & (pf * {Syn,Fin,Rst,Urg,Ack} = {Ack}) &
  2145. (~DoRFC1323 OR ~(TSPresent IN lf) OR (tsval - p.tsrecent >= 0)) & (seq = p.rcvnxt) &
  2146. (win # 0) & (win = p.sndwnd) & (p.sndnxt = p.sndmax) THEN
  2147. IF DoRFC1323 & (TSPresent IN lf) & (seq - p.lastacksent <= 0) THEN
  2148. p.tsrecentage := timeSource.now;
  2149. p.tsrecent := tsval; (* see p. 937 & fig. 26.20 *)
  2150. END;
  2151. IF tlen = 0 THEN
  2152. IF (ack - p.snduna > 0) & (ack - p.sndmax <= 0) & (p.sndcwnd >= p.sndwnd) & (p.dupacks < ReXmtThresh) THEN
  2153. (* p.dupacks < ReXmtThres fix from "Performance Problems in 4.4BSD TCP" *)
  2154. Machine.AtomicInc(NTCPPredAck);
  2155. IF DoRFC1323 & (TSPresent IN lf) THEN XmitTimer(p, timeSource.now - tsecr + 1)
  2156. ELSIF (p.rtt # 0) & (ack - p.rtseq > 0) THEN XmitTimer(p, p.rtt)
  2157. ELSE (* skip *)
  2158. END;
  2159. acked := ack - p.snduna;
  2160. Machine.AtomicInc(NTCPAckPack); Machine.AtomicAdd(NTCPAckByte, acked);
  2161. SbDrop(p, acked);
  2162. p.snduna := ack;
  2163. IF ack = p.sndmax THEN p.timer[ReXmt] := 0
  2164. ELSIF p.timer[Persist] = 0 THEN
  2165. p.timer[ReXmt] := p.rxtcur;
  2166. ELSE (* skip *)
  2167. END;
  2168. (*IF Notify IN p.flags THEN SoWakeup(p) END;*)
  2169. IF p.sndcc # 0 THEN Output(p) END;
  2170. RETURN
  2171. END
  2172. ELSIF (ack = p.snduna) & (p.rcvreasm = NIL) & (tlen <= p.rcvspace) THEN
  2173. Machine.AtomicInc(NTCPPredData);
  2174. Machine.AtomicInc(NTCPRcvPackFast);
  2175. Machine.AtomicAdd(NTCPRcvByteFast, tlen);
  2176. (* can assume no overlap with last or next buffers *)
  2177. Reasm; (* queue the buffer directly *)
  2178. (*SoWakeup(p);*)
  2179. INCL(p.flags, DelAck);
  2180. RETURN
  2181. ELSE
  2182. (* skip - continue to slow path *)
  2183. END
  2184. END;
  2185. (* slow path *)
  2186. p.rcvwnd := MAX(MAX(p.rcvspace, 0), p.rcvadv - p.rcvnxt);
  2187. CASE p.state OF
  2188. Listen:
  2189. IF ProcessListen() THEN Trim1 ELSE RETURN END
  2190. |SynSent:
  2191. IF ProcessSynSent() THEN Trim1 ELSE RETURN END
  2192. ELSE
  2193. IF DoRFC1323 & ~Paws() THEN RETURN END;
  2194. IF (p.rcvnxt - seq > 0) & ~Trim2(p.rcvnxt - seq) THEN RETURN END;
  2195. (*IF (Gone IN p.flags) & (p.state > CloseWait) & (tlen # 0) THEN
  2196. CloseConnection(p); Machine.AtomicInc(NTCPRcvAfterClose); GotoDropReset; RETURN
  2197. END;*)
  2198. IF ((seq + tlen) - (p.rcvnxt + p.rcvwnd) > 0) & ~Trim3((seq + tlen) - (p.rcvnxt + p.rcvwnd)) THEN RETURN END;
  2199. IF DoRFC1323 & (TSPresent IN lf) & (seq - p.lastacksent <= 0) THEN RecordTS END;
  2200. IF (Rst IN pf) & ~ProcessRst() THEN RETURN END;
  2201. IF Syn IN pf THEN Drop(p, ConnectionReset); GotoDropReset; RETURN END;
  2202. IF ~(Ack IN pf) THEN GotoDrop; RETURN END;
  2203. IF ~ProcessAck() THEN RETURN END;
  2204. END; (* CASE *)
  2205. IF ~Step6() THEN RETURN END;
  2206. DoData;
  2207. END ProcessInput;
  2208. (* Initialize a new Connection. *)
  2209. PROCEDURE InitConnection(p: Connection);
  2210. VAR
  2211. buf: SendBuffer;
  2212. BEGIN
  2213. IF ~NewZeros THEN (* clear all fields *)
  2214. CancelTimers(p);
  2215. p.fip := IP.NilAdr; p.fport := NilPort; p.rxtshift := 0; p.dupacks := 0;
  2216. p.snduna := 0; p.sndnxt := 0; p.sndup := 0; p.sndwl1 := 0; p.sndwl2 := 0; p.iss := 0;
  2217. p.sndwnd := 0; p.rcvwnd := 0; p.rcvnxt := 0; p.rcvup := 0; p.irs := 0; p.rcvadv := 0;
  2218. p.sndmax := 0; p.idle := 0; p.rtt := 0; p.rtseq := 0; p.maxsndwnd := 0;
  2219. p.sndscale := 0; p.rcvscale := 0; p.requestrscale := 0; p.requestedsscale := 0;
  2220. p.tsrecent := 0; p.tsrecentage := 0; p.lastacksent := 0; p.error := 0; p.acceptable := 0;
  2221. p.sndcc := 0; p.poolNext := NIL; p.parent := NIL; p.acceptNext := NIL
  2222. END;
  2223. (* initialize fields *)
  2224. p.maxseg := MSS; p.state := Closed;
  2225. IF DoRFC1323 THEN p.flags := {ReqScale,ReqTstmp} ELSE p.flags := {} END;
  2226. p.srtt := SRTTBase; p.rttvar := SRTTDflt * 4; p.rttmin := MinTime;
  2227. RangeSet(p.rxtcur, (SRTTBase DIV 4 + SRTTDflt * 4) DIV 2, MinTime, ReXmtMax);
  2228. p.sndcwnd := ASH(MaxWin, MaxWinShift);
  2229. p.sndssthresh := ASH(MaxWin, MaxWinShift);
  2230. p.sndspace := MaxSendSpace;
  2231. p.rcvspace := MaxRecvSpace;
  2232. p.rcvhiwat := MaxRecvSpace;
  2233. WHILE (p.requestrscale < MaxWinShift) & (ASH(MaxWin, p.requestrscale) < p.rcvhiwat) DO
  2234. INC(p.requestrscale)
  2235. END;
  2236. Machine.AtomicInc(NTCPNewBufs);
  2237. (* allocate send buffer *)
  2238. NEW(buf); NEW(buf.data, MSS * SegsPerBuf);
  2239. IF ~NewZeros THEN buf.ofs := 0; buf.len := 0; END;
  2240. buf.next := buf; p.sndhead := buf; p.sndtail := buf;
  2241. NEW(p.sndcontig, MSS);
  2242. (* init receive buffer *)
  2243. p.rcvhead := NIL;
  2244. END InitConnection;
  2245. (* Move connection to next state in close process. *)
  2246. PROCEDURE UsrClosed(p: Connection);
  2247. BEGIN
  2248. CASE p.state OF
  2249. Closed, Listen, SynSent:
  2250. p.state := Closed; CloseConnection(p)
  2251. |SynReceived, Established:
  2252. p.state := FinWait1
  2253. |CloseWait:
  2254. p.state := LastAck
  2255. ELSE (* skip *)
  2256. END;
  2257. (*IF p.state >= FinWait2 THEN SoIsDisconnected(p) END*)
  2258. END UsrClosed;
  2259. (* If t is not zero, decrement it. Return true if it has reached 0, false otherwise. *)
  2260. PROCEDURE Expired(VAR t: LONGINT): BOOLEAN;
  2261. BEGIN
  2262. IF t # 0 THEN DEC(t); RETURN t = 0 ELSE RETURN FALSE END
  2263. END Expired;
  2264. PROCEDURE GetID(): LONGINT;
  2265. VAR id, time, date: LONGINT;
  2266. BEGIN
  2267. Clock.Get(time, date);
  2268. id := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, time) / SYSTEM.VAL(SET, date));
  2269. RETURN id;
  2270. END GetID;
  2271. (** Aos command - display all errors *)
  2272. PROCEDURE DisplayErrors*(context : Commands.Context);
  2273. VAR i: LONGINT;
  2274. BEGIN
  2275. FOR i := 1 TO NumErrors-1 DO
  2276. IF NTCPError[i] # 0 THEN
  2277. context.out.String("TCP: Error "); context.out.Int(i+MinError, 1);
  2278. context.out.String(" "); context.out.Int(NTCPError[i], 1); context.out.Ln;
  2279. END;
  2280. END;
  2281. END DisplayErrors;
  2282. (** Aos command - discard and finalize all connections *)
  2283. PROCEDURE DiscardAll*;
  2284. BEGIN
  2285. pool.Finalize();
  2286. END DiscardAll;
  2287. (** Temporary trace procedure. *)
  2288. PROCEDURE ToggleTrace*;
  2289. BEGIN
  2290. trace := ~trace;
  2291. KernelLog.Enter; KernelLog.String("TCP trace ");
  2292. IF trace THEN KernelLog.String("on") ELSE KernelLog.String("off") END;
  2293. KernelLog.Exit
  2294. END ToggleTrace;
  2295. PROCEDURE Init;
  2296. VAR i: LONGINT;
  2297. BEGIN
  2298. FOR i := 0 TO MaxRxtShift DO
  2299. IF i < 6 THEN backoff[i] := ASH(1, i) ELSE backoff[i] := 64 END;
  2300. INC(totbackoff, backoff[i])
  2301. END;
  2302. (* maxdiff := 0;*)
  2303. (* backoff[0]:=1;
  2304. backoff[1]:=1;
  2305. backoff[2]:=2;
  2306. backoff[3]:=3;
  2307. backoff[4]:=5;
  2308. backoff[5]:=10;
  2309. backoff[6]:=18;
  2310. backoff[7]:=30;
  2311. backoff[8]:=60;
  2312. backoff[9]:=120;
  2313. backoff[10]:=240;
  2314. backoff[11]:=240;
  2315. backoff[12]:=240;*)
  2316. ASSERT(MaxRxtShift=12);
  2317. totbackoff := 0;
  2318. FOR i:=0 TO MaxRxtShift DO
  2319. INC(totbackoff, backoff[i]);
  2320. END;
  2321. (* Flags used when sending segments in tcp_output. Basic flags {Rst, Ack, Syn, Fin} are totally determined by state, with the proviso that Fin is sent only if all data queued for output is included in the segment. The {Psh,Urg} flags are set as necessary.
  2322. *)
  2323. outflags[Closed] := {Rst,Ack}; outflags[Listen] := {}; outflags[SynSent] := {Syn};
  2324. outflags[SynReceived] := {Syn,Ack}; outflags[Established] := {Ack};
  2325. outflags[CloseWait] := {Ack}; outflags[FinWait1] := {Fin,Ack}; outflags[Closing] := {Fin,Ack};
  2326. outflags[LastAck] := {Fin,Ack}; outflags[FinWait2] := {Ack}; outflags[TimeWait] := {Ack};
  2327. (* other globals *)
  2328. NEW(nilpcb);
  2329. nilpcb.lport := -1; (* can never match *)
  2330. nilpcb.int := NIL;
  2331. IF ~NewZeros THEN nilpcb.rcvspace := 0; nilpcb.rcvscale := 0 END; (* for Respond *)
  2332. lastpcb := nilpcb;
  2333. NEW(empty, 1);
  2334. NEW(pool);
  2335. NEW(issSource, GetID());
  2336. NEW(timeSource)
  2337. END Init;
  2338. PROCEDURE Cleanup;
  2339. BEGIN
  2340. IP.RemoveReceiver(IPTypeTCP);
  2341. pool.Finalize();
  2342. timeSource.Finalize();
  2343. END Cleanup;
  2344. BEGIN
  2345. ASSERT(~DoRFC1323 OR (ProcOptions & GenOptions)); (* constants should make sense *)
  2346. ASSERT(SYSTEM.VAL(LONGINT, {Fin}) = 1); (* bit order for flags cast in Input, Output and Respond *)
  2347. ASSERT((TimerPeriod MOD FastPeriod = 0) & (TimerPeriod MOD SlowPeriod = 0));
  2348. trace := FALSE;
  2349. Init();
  2350. IP.InstallReceiver(IPTypeTCP, Input);
  2351. Modules.InstallTermHandler(Cleanup);
  2352. END TCP.
  2353. (*
  2354. History:
  2355. 08.11.2003 mvt Changed for new interface of IP and Network.
  2356. 08.11.2003 mvt Fixed array position error in ProcessOptions().
  2357. 09.11.2003 mvt Min()/Max() functions now in inline assembler.
  2358. 10.11.2003 mvt Added InterfaceClosed detection in Connection.SlowTimer().
  2359. 10.11.2003 mvt Added correct finalization of Connection, ConnectionPool, Timer and the module itself.
  2360. 11.11.2003 mvt Completely changed receive buffer queueing, integrated Network buffers directly.
  2361. 12.11.2003 mvt Completely changed ConnectionPool, now working with a hash table.
  2362. 12.12.2003 mvt Bugfixed entire module by comparing it with the book.
  2363. 12.12.2003 mvt Completed header prediction code according to the book.
  2364. 12.12.2003 mvt Added support for RFC1323 (timestamp, PAWS).
  2365. 12.12.2003 mvt Added support for window scaling (for windows >64KB).
  2366. 14.02.2004 mvt Fixed reassembly bug in Reasm().
  2367. 14.02.2004 mvt Fixed MSS option sending bug in Output().
  2368. 28.02.2004 mvt Fixed early Fin sending bug in Output().
  2369. 04.03.2004 rp Fixed & (p.dupacks < ReXmtThresh) in Step6 according to ftp://ftp.cs.arizona.edu/xkernel/papers/tcp_problems.ps
  2370. 04.03.2004 rp Fixed XmitTimer according to ftp://ftp.cs.arizona.edu/xkernel/papers/tcp_problems.ps
  2371. 02.05.2005 eb Supports IPv6 (WritePseudoHdr) and fragmented IP packets.
  2372. *)
  2373. (*
  2374. * Copyright (c) 1982, 1986, 1993
  2375. * The Regents of the University of California. All rights reserved.
  2376. *
  2377. * Redistribution and use in source and binary forms, with or without
  2378. * modification, are permitted provided that the following conditions
  2379. * are met:
  2380. * 1. Redistributions of source code must retain the above copyright
  2381. * notice, this list of conditions and the following disclaimer.
  2382. * 2. Redistributions in binary form must reproduce the above copyright
  2383. * notice, this list of conditions and the following disclaimer in the
  2384. * documentation and/or other materials provided with the distribution.
  2385. * 3. All advertising materials mentioning features or use of this software
  2386. * must display the following acknowledgement:
  2387. * This product includes software developed by the University of
  2388. * California, Berkeley and its contributors.
  2389. * 4. Neither the name of the University nor the names of its contributors
  2390. * may be used to endorse or promote products derived from this software
  2391. * without specific prior written permission.
  2392. *
  2393. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  2394. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  2395. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  2396. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  2397. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  2398. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  2399. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  2400. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  2401. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  2402. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  2403. * SUCH DAMAGE.
  2404. *)
  2405. (* pjm:
  2406. Gigabit:
  2407. Alteon AceNIC / 3Com 3C985 / NetGear GA620 Gigabit Ethernet Adapter
  2408. http://sanjose.alteon.com/open.shtml
  2409. Linux Driver
  2410. http://home.cern.ch/~jes/gige/acenic.html
  2411. Packet Engines Hamachi Driver
  2412. http://www.nscl.msu.edu/~kasten/perf/hamachi/
  2413. A Connection has to react to external and internal events
  2414. 1. User calls (external)
  2415. Connection.Open
  2416. Connection.Send
  2417. Connection.Receive
  2418. Connection.Available
  2419. Connection.Close
  2420. 2. Timer.HandleTimeout (internal)
  2421. Connection.DelayedAck
  2422. Connection.SlowTimer
  2423. 3. Packet arrival (external)
  2424. Connection.Input (from Input)
  2425. The Timer reacts to external and internal events
  2426. 1. Timer.HandleTimeout (external)
  2427. 2. Timer.GetISS (internal - only called from Connection.Open, which is only called externally)
  2428. The ConnectionPool reacts to external and internal events
  2429. 1. Lookup (internal)
  2430. 2. Enumerate (external)
  2431. 3. Add (internal)
  2432. 4. Remove (internal)
  2433. *)