Author SHA1 Message Date
evgeny f5bae735f9 Record successful two-PIN pairing and branch regression validation 2026-11-03 01:43:00 +01:00
evgeny 20571b7a95 Test losses in both PIN phases and reject premature keys; update CLI guidance 2026-11-03 01:37:58 +01:00
evgeny b04a57308f Document reciprocal PIN protocol and explicit pairing recovery menu 2026-11-03 01:35:52 +01:00
evgeny c9b1a8d0cb Translate pairing menu and reciprocal PIN instructions on desktop 2026-11-03 01:35:20 +01:00
evgeny e36e16f139 Test explicit self pairing menu, resume, and both PIN input steps 2026-11-03 01:35:19 +01:00
evgeny f2a2983986 Explain both pairing PIN steps in English and Russian on Android 2026-11-03 01:34:42 +01:00
evgeny 18f1c6aaf0 Support explicit pairing menu and return PIN on Android 2026-11-03 01:34:42 +01:00
evgeny 10bafe3ca3 Open device pairing explicitly from self context menu and show both PIN steps 2026-11-03 01:31:58 +01:00
evgeny bc2ac140a8 Require reciprocal PIN confirmation before device key transfer 2026-11-03 01:31:47 +01:00
evgeny eb2e676d0a Document explicit device linking flow and outstanding host test issues 2026-11-03 00:47:04 +01:00
evgeny 891e580b7c Verify deleted-device exclusion in owner view and capture pairing guidance 2026-11-03 00:45:57 +01:00
evgeny eb6ec1f2ca Include confirmation dialog type in member interaction tests 2026-11-03 00:44:49 +01:00
evgeny d8b63dfad8 Include device-group operation state required by the Android member UI 2026-11-03 00:43:20 +01:00
evgeny 029ed59fbf Verify eligible device actions, confirmation gating and incoming PIN guidance 2026-11-03 00:43:01 +01:00
evgeny add270d35b Translate device linking explanations and explicit start action 2026-11-03 00:42:41 +01:00
evgeny 6d75232d8b Explain incoming device linking and preserve self disconnect in properties 2026-11-03 00:39:06 +01:00
evgeny 18ae58a3d2 Move device linking into an eligible member context action with confirmation 2026-11-03 00:36:24 +01:00
evgeny 10e7eeee3f Check formatting help placement and document flexible code fences 2026-11-03 00:29:18 +01:00
evgeny 1d323a1db6 Explain whitespace around code fences in both help translations 2026-11-03 00:29:18 +01:00
evgeny de30c76429 Allow whitespace around standalone code fences and language labels 2026-11-03 00:29:00 +01:00
evgeny f147f346d5 Add message formatting help beside Join with a fenced code example 2026-11-03 00:28:09 +01:00
evgeny be7421e6e2 Verify visible copy confirmation, expiry and repeated clicks 2026-11-03 00:25:23 +01:00
evgeny 2cc3451721 Translate code Copy confirmation into Russian 2026-11-03 00:24:46 +01:00
evgeny fff5834a01 Show temporary Copied feedback after copying a code block 2026-11-03 00:24:46 +01:00
evgeny c91a217c0c Keep context menu selection and member details on the same target 2026-11-03 00:22:52 +01:00
evgeny 913e4dfbd4 Reproduce member selection jumping back while its context menu is open 2026-11-03 00:22:29 +01:00
evgeny f29554f92b Check the exact scroll threshold and only notify successful sends 2026-11-03 00:20:04 +01:00
evgeny 804a684ef7 Use the test logger for history scroll diagnostics 2026-11-03 00:19:06 +01:00
evgeny be4798a595 Test group and PM bottom following with long messages and historical sends 2026-11-03 00:18:32 +01:00
evgeny 0da3c3a677 Follow new messages near the bottom and always follow accepted sends 2026-11-03 00:16:33 +01:00
evgeny 39a9fe01a3 Expose accepted sends and define history follow policy 2026-11-03 00:16:21 +01:00
evgeny 3c40294d08 Verify header language names for explicit and detected code blocks 2026-11-03 00:12:39 +01:00
evgeny c1daeb4982 Show resolved code language on the left of each block header 2026-11-03 00:12:23 +01:00
evgeny 54b1a4fbe5 Check Copy hover cursor and document block copying 2026-11-02 23:54:01 +01:00
evgeny f8e6e9e5d4 Configure Copy hover detection through the existing view callback pattern 2026-11-02 23:54:00 +01:00
evgeny 8a2f9418e8 Use a complete dark palette for code Copy interaction checks 2026-11-02 23:53:00 +01:00
evgeny 997dab2514 Keep code Copy inactive after dragging back onto its button 2026-11-02 23:52:28 +01:00
evgeny f0bb9c05bf Verify code Copy buttons across themes and reject drags or changed messages 2026-11-02 23:51:14 +01:00
evgeny 61aafac32d Draw Copy controls for code blocks and copy complete block on click 2026-11-02 23:50:42 +01:00
evgeny f7e82c04a7 Reserve code block headers and share Copy button geometry 2026-11-02 23:50:22 +01:00
evgeny ffcb02354f Check embedded translations using each catalog context 2026-11-02 23:35:24 +01:00
evgeny 780e7220c3 Include model roles and row actions required by subgroup details 2026-11-02 23:34:22 +01:00
evgeny 49b7ac9099 Include translations for subgroup name editing 2026-11-02 23:34:07 +01:00
evgeny f2529fd624 Include subgroup rename command used by the member context menu 2026-11-02 23:34:06 +01:00
evgeny 80c645c982 Show subgroup members without a detail title or rename button 2026-11-02 23:20:18 +01:00
evgeny 5c92241488 Document language detection rules and GitHub corpus results 2026-11-02 23:10:39 +01:00
evgeny bf663d5799 Recognize Java method fragments without package declarations 2026-11-02 23:09:33 +01:00
evgeny 34b71c040e Ignore multiline literals when detecting code language 2026-11-02 23:08:37 +01:00
evgeny 6ea6bf20a8 Avoid guessing JavaScript from shared let and arrow syntax 2026-11-02 23:07:48 +01:00
evgeny 970cdd5441 Add reproducible pinned GitHub corpus for language detection 2026-11-02 23:06:43 +01:00
evgeny 51d24ca315 Verify automatic highlighting and explicit language precedence 2026-11-02 23:06:24 +01:00
evgeny 99b4bea3f7 Distinguish Rust paths and embedded markup in language detection 2026-11-02 23:03:30 +01:00
evgeny 032b084a15 Apply language detection to unlabelled code and add corpus runner 2026-11-02 23:00:45 +01:00
evgeny a7d964658c Add bounded heuristic code language detector 2026-11-02 23:00:10 +01:00
evgeny 39a2895074 Process window startup requests before testing geometry saves 2026-11-02 22:49:15 +01:00
evgeny 53f8efa920 Record settings window geometry test failure 2026-11-02 22:46:59 +01:00
evgeny 747519ab99 Link message formatting before inheriting GUI test dependencies 2026-11-02 22:46:11 +01:00
evgeny 931b9822c3 Update italic markup examples and regression cases 2026-11-02 22:42:13 +01:00
evgeny 66b8da36b8 Use double underscores for italic chat markup 2026-11-02 22:42:13 +01:00
evgeny b17c6fff96 Document desktop message formatting and syntax highlighting dependencies 2026-11-02 22:37:55 +01:00
evgeny c19750a800 Handle Windows line endings and verify empty code blocks 2026-11-02 22:36:10 +01:00
evgeny 77186c4392 Verify formatted message drag-copy and automatic Windows dependency installation 2026-11-02 22:33:27 +01:00
evgeny 347c744f27 Test message markup, syntax state and formatted text layout 2026-11-02 22:31:49 +01:00
evgeny fc45b39948 Install missing Windows GUI dependencies before configuring the build 2026-11-02 22:30:48 +01:00
evgeny 31b42d0c22 Render formatted chat text with matching selection and clipboard 2026-11-02 22:29:50 +01:00
evgeny 3a6844fc9d Add desktop message markup parser and syntax highlighting preparation 2026-11-02 22:29:02 +01:00
evgeny 5a8a50e74c Fix desktop message selection highlight paragraph offset 2026-11-02 22:18:41 +01:00
evgeny 7062905d48 Add simultaneous calls to device groups 2026-11-02 21:53:20 +01:00
evgeny 24cb0eb463 Refine device group controls and aggregate status indicators 2026-11-02 21:02:14 +01:00
evgeny 03fea5eb74 Refine device pairing flow and invalidate outdated node snapshots 2026-11-02 19:52:18 +01:00
evgeny d7006aecb5 Add signed device groups and compact NODEINFO packing 2026-11-02 18:47:58 +01:00
evgeny ef34f81c90 Document device group implementation requirements 2026-11-02 16:17:03 +01:00
evgeny 26f8491abc Add missing desktop voice compressor controls 2026-11-02 16:17:03 +01:00
evgeny 1c0f40f247 Accept zero compressor gain and clarify Android storage limits 2026-11-02 16:17:03 +01:00
evgeny 2260719ff7 Add signed Android release build scripts 2026-11-02 15:03:46 +01:00
evgeny 3166ee7a41 Remove unused log file field from Android settings 2026-11-02 15:03:45 +01:00
evgeny 2b5b5aad88 Fix group JOIN retry delays after rejection and transport failure 2026-11-02 00:33:55 +01:00
evgeny ba6306f396 Give independent stream test an explicit BGP group owner 2026-11-01 23:24:14 +01:00
evgeny 2414207e80 Document online requirement for opening stream subscriptions 2026-11-01 23:23:44 +01:00
evgeny d87fb7c555 Clarify BGP availability and source watcher documentation 2026-11-01 23:23:25 +01:00
evgeny 9b416fad82 Test BGP stream availability, recovery and offline viewer cleanup 2026-11-01 23:22:48 +01:00
evgeny 5b5a5e94e3 Remove offline Android streams without draining playback 2026-11-01 23:21:39 +01:00
evgeny 83f6a79985 Report offline stream sources in Android playback 2026-11-01 23:21:39 +01:00
evgeny bf63f79fdf Show offline stream closure in the desktop player 2026-11-01 23:10:27 +01:00
evgeny 46a5cf14ce Close stream receivers when their source goes offline in BGP 2026-11-01 23:10:00 +01:00
evgeny 2f94da7bbf Test Android stream audio switching and cleanup ownership 2026-11-01 23:06:32 +01:00
evgeny 2b268f314f Switch Android playback clocks when stream audio changes 2026-11-01 23:05:57 +01:00
evgeny 4e28c518bd Verify remote no-audio readiness independently of the audio buffer 2026-11-01 22:52:18 +01:00
evgeny 827f3dc619 Declare source audio state in live playback and drain fixtures 2026-11-01 22:48:36 +01:00
evgeny cbe4cb1e33 Use video playback clocks when the source disables audio 2026-11-01 22:48:19 +01:00
evgeny 0bd046adca Reserve telemetry width for playback catch-up speed 2026-11-01 22:29:29 +01:00
evgeny b414fc9538 Verify the bottom player bar and logarithmic volume output 2026-11-01 22:23:49 +01:00
evgeny 5a8807bf89 Keep multiview captions and controls below video and use logarithmic volume 2026-11-01 22:23:09 +01:00
evgeny 213a1010c2 Move live player controls below video with a triangular volume scale 2026-11-01 22:22:44 +01:00
evgeny c91782848f Use the red crossed microphone for the no-audio source selection 2026-11-01 22:11:35 +01:00
evgeny 515645dac5 Cross out the red microphone icon when stream audio is off 2026-11-01 22:10:25 +01:00
evgeny a2d700d5a6 Show the same microphone icon in red when stream audio is off 2026-11-01 22:09:39 +01:00
evgeny 44b7efb1ce Show microphone mute icons on the stream audio button 2026-11-01 22:05:41 +01:00
evgeny fabc76ef82 Keep microphone and no-audio options available during publication 2026-11-01 22:05:10 +01:00
evgeny 3eff460457 Allow desktop stream audio to be enabled and disabled live 2026-11-01 22:04:23 +01:00
evgeny 1a113f953b Verify video continues after microphone samples stop 2026-11-01 21:56:31 +01:00
evgeny f7096bba7d Continue streaming without audio after a 300 ms microphone timeout 2026-11-01 21:54:47 +01:00
evgeny 83183f9885 Test live microphone changes and video-only startup 2026-11-01 21:42:45 +01:00
evgeny 1a413608ca Start desktop streams without audio when capture is unavailable 2026-11-01 21:39:26 +01:00
evgeny 1719f8e108 Save shared stream microphone through the main window 2026-11-01 21:38:36 +01:00
evgeny fbc030dc5b Share radio microphone controls with desktop publication 2026-11-01 21:38:01 +01:00
evgeny b2bd2c284c Use shared microphone selection for live desktop streams 2026-11-01 21:37:37 +01:00
evgeny 4338f1f9c8 Skip Windows drive roots when creating attachment directories 2026-11-01 21:30:23 +01:00
evgeny 8e204ef887 Log precise directory creation errors when preparing attachments 2026-11-01 21:02:47 +01:00
evgeny 8074b73e95 Verify blocked Bluetooth device close through the actual WinRT cleanup path 2026-11-01 20:49:44 +01:00
evgeny 27d51e93b7 Update diagnostic filters, codec regression and BLE debugging instructions 2026-11-01 20:41:02 +01:00
evgeny 8336487596 Move desktop video and publisher diagnostics out of temporary debug category 2026-11-01 20:40:13 +01:00
evgeny 811f5b7659 Keep packet reception and FFmpeg diagnostics in their module categories 2026-11-01 20:40:13 +01:00
evgeny b0fe663109 Move ETCP packet and carrier diagnostics from debug to etcp trace 2026-11-01 20:39:35 +01:00
evgeny 8ca7c3cc15 Trace BLE cleanup phases and distinguish closing from completed teardown 2026-11-01 20:39:07 +01:00
evgeny 0308d4a702 Add independent diagnostics for stalled BLE WinRT cleanup calls 2026-11-01 20:37:44 +01:00
evgeny d7e5672261 Record capture shutdown verification and pending Windows device check 2026-11-01 20:31:12 +01:00
evgeny fff072d0a8 Identify capture process failures and record forced exits accurately 2026-11-01 20:30:22 +01:00
evgeny 95425aacab Defer capture rollback and bind errors to the failed configuration 2026-11-01 20:27:17 +01:00
evgeny 96e4c72027 Align stream preview documentation with isolated CPU capture 2026-11-01 20:25:57 +01:00
evgeny 05e1b1e037 Verify rollback continuity and enumerate test windows through capture IPC 2026-11-01 20:25:14 +01:00
evgeny 093d8f15e4 Check asynchronous missing-camera errors in publisher tests 2026-11-01 20:20:23 +01:00
evgeny 006d45024b Make capture cleanup idempotent and identify frame release stalls 2026-11-01 20:20:00 +01:00
evgeny caf4ab406c Document isolated stream capture shutdown and diagnostics 2026-11-01 20:18:34 +01:00
evgeny 8c2289b188 Preserve call camera geometry before stream orientation transforms 2026-11-01 20:17:15 +01:00
evgeny 14bdd2a58f Pass only immutable source identifiers into the publisher 2026-11-01 20:15:42 +01:00
evgeny 61663e261d Keep capture lifecycle diagnostics in the video category 2026-11-01 20:15:03 +01:00
evgeny cf356ee647 Refresh capture devices through IPC and diagnose unexpected backend stops 2026-11-01 20:14:07 +01:00
evgeny 8faaa34e24 Complete capture API migration and cancel prelaunch stop requests 2026-11-01 20:13:07 +01:00
evgeny 939f33773b Verify capture timeout diagnostics and large-frame ownership 2026-11-01 20:11:12 +01:00
evgeny b34825cda0 Exercise hung capture stop and destruction without blocking publisher GUI 2026-11-01 20:10:31 +01:00
evgeny 4ab0be1882 Test stream UI with process-owned sources and CPU previews 2026-11-01 20:08:58 +01:00
evgeny a02465217b Keep capture completion observable and retain session ownership through stop 2026-11-01 20:08:01 +01:00
evgeny eed07cb358 Feed publisher CPU frames and decouple FIN from capture teardown 2026-11-01 20:06:56 +01:00
evgeny 5256dfa8c5 Use shared capture worker for calls and build screen backends there 2026-11-01 20:04:50 +01:00
evgeny e299a9b30b Isolate screen capture lifecycle and report worker close stages 2026-11-01 20:04:13 +01:00
evgeny 48998b440f Extract shared video capture process contracts 2026-11-01 20:02:12 +01:00
evgeny e384d4cf3d Add desktop network traffic graphs and unify microphone icons 2026-11-01 14:45:01 +01:00
evgeny 3dff681ff0 Unify channel action icons and add a drawn settings gear 2026-11-01 10:54:41 +01:00
evgeny a77a41f068 Refine composer icons with consistent vector outlines 2026-11-01 10:29:16 +01:00
evgeny 46b3296a36 Match composer microphone and attachment icons to Android 2026-11-01 10:10:49 +01:00
evgeny c889928e52 Show FFmpeg driver errors when hardware encoding fails 2026-11-01 08:24:43 +01:00
evgeny d8db018166 Focus the message input when the chat window is activated 2026-11-01 05:49:06 +01:00
evgeny 4e3c1182db Offer JPEG and PNG clipboard attachments with automatic selection 2026-10-31 22:30:57 +01:00
evgeny 4d30fa6bcc Support pasting clipboard images as PNG attachments 2026-10-31 22:13:11 +01:00
evgeny c8012d35f1 Limit ETCP TCP link MTU to 1500 bytes 2026-10-31 21:35:10 +01:00
evgeny 57168e4a16 Update startup regression for skipped automatic TCP listeners 2026-10-31 20:12:08 +01:00
evgeny c8388ba8ba Cover IPv6 bind failure and offline startup in socket regressions 2026-10-31 20:08:26 +01:00
evgeny 84e26dcf00 Test automatic socket failures and recovery without startup rollback 2026-10-31 20:07:16 +01:00
evgeny 60af36902c Skip unavailable automatic sockets and retain working transports 2026-10-31 20:06:17 +01:00
evgeny 4f2ad13e39 Preserve socket bind errors through resource cleanup 2026-10-31 20:05:46 +01:00
evgeny 5b531ddae7 Improve Android proximity settings and channel scanner layout 2026-10-31 18:29:09 +01:00
evgeny 2c89490794 Cover maximized media restoration and destruction during playback 2026-10-31 18:03:26 +01:00
evgeny 4764a7dd23 Restore the normal media rectangle explicitly when leaving fullscreen 2026-10-31 18:02:16 +01:00
evgeny 8ab294fb30 Fit media frames inside monitors and close video before widget teardown 2026-10-31 18:01:41 +01:00
evgeny 703f4a4a60 Keep complete diagnostics for media monitor restoration failures 2026-10-31 18:00:16 +01:00
evgeny 68065d4a79 Document viewer geometry ownership and gate the offscreen monitor fixture 2026-10-31 17:58:34 +01:00
evgeny 6a1b7c5363 Verify media geometry survives restarts on each physical monitor 2026-10-31 17:57:56 +01:00
evgeny db1c2f0da7 Test cached media geometry and stable video windows across file loads 2026-10-31 17:56:34 +01:00
evgeny c0d5aac41c Use explicit wide bounds when restoring media coordinates 2026-10-31 17:55:06 +01:00
evgeny 2a0374e2ae Persist shared chat media geometry and the physical monitor per profile 2026-10-31 17:53:16 +01:00
evgeny 1d9570e38b Keep video playback geometry and use the actual fullscreen state 2026-10-31 17:51:48 +01:00
evgeny 74d95bc9c4 Preserve shared PTT ownership on panel cleanup and avoid repeated reset logs 2026-10-31 17:32:25 +01:00
evgeny 165f5e6c63 Test the shared lock indicator and unlocking PTT across input sources 2026-10-31 17:32:13 +01:00
evgeny d25d097287 Let the hotkey toggle the common PTT latch without a second latch state 2026-10-31 17:31:24 +01:00
evgeny 3d0f3213f8 Display and release the shared PTT latch from the radio button 2026-10-31 17:30:54 +01:00
evgeny febaf3d350 Store the shared button and keyboard PTT latch in the radio engine 2026-10-31 17:30:38 +01:00
evgeny 4b23fa2b63 Verify hotkey double-press preference survives reopening settings 2026-10-31 17:22:02 +01:00
evgeny 80935eb2a5 Exercise global PTT polling and checkbox independence under X11 2026-10-31 17:21:03 +01:00
evgeny 99f4121a31 Translate the single PTT hotkey and double-press option 2026-10-31 17:20:25 +01:00
evgeny 83f16d8dcd Cover single portal assignment and optional hotkey locking 2026-10-31 17:19:56 +01:00
evgeny d1a62c51ef Persist optional double-press locking for the radio hotkey 2026-10-31 17:19:23 +01:00
evgeny 11e9946549 Show one radio shortcut and a hotkey double-press checkbox 2026-10-31 17:19:11 +01:00
evgeny 497ecd5d15 Register one Wayland PTT shortcut and reset latches on session changes 2026-10-31 17:17:31 +01:00
evgeny 239c4f7a7a Use one global PTT shortcut with double-press latching 2026-10-31 17:17:04 +01:00
evgeny a708e9494a Add single PTT hotkey hold and double-press state 2026-10-31 17:16:30 +01:00
evgeny 170ccf5db6 Fix Windows camera error encoding and add camera context 2026-10-31 16:08:44 +01:00
evgeny a7da1e3286 Preserve Windows camera error text with UTF-8 code page 2026-10-31 15:35:46 +01:00
evgeny db414a0042 Record successful Windows BLE GATT profile radio probe 2026-10-31 14:38:09 +01:00
evgeny 51a0e3f9f2 Use one GATT advertisement and read full BLE node profiles 2026-10-31 14:35:37 +01:00
evgeny 5d265dbd28 Cancel queued Android BLE sends after link closure 2026-10-31 12:20:47 +01:00
evgeny f3813b1a56 Show available receive buffer headroom in call audio graphs 2026-10-31 10:48:06 +01:00
evgeny ee0c92b9d8 Fix delayed router epoch confirmation and collapse duplicate BLE links 2026-10-31 10:22:22 +01:00
evgeny 0915c8ad2e Stabilize call batching and sole BLE retransmission timing 2026-10-31 09:12:18 +01:00
evgeny 92a58fe285 Speed up Windows installer compression 2026-10-31 01:03:03 +01:00
evgeny 2d92a003fc Keep connection property changes from refreshing BLE discovery 2026-10-31 00:53:11 +01:00
evgeny 2c2fd09323 Seed cached BlueZ service identities without refreshing discovery age 2026-10-31 00:51:54 +01:00
evgeny 17c22eb562 Verify one BlueZ advertisement and independent visibility and admission 2026-10-31 00:40:59 +01:00
evgeny d00a642c49 Define BLE v5 visibility, admission and bounded publication contracts 2026-10-31 00:37:11 +01:00
evgeny 5deb6de7ee Verify canonical UUID conversion across WinRT GUID byte order 2026-10-31 00:36:16 +01:00
evgeny 67a76b4119 Test and probe Windows single-provider discovery lifecycle 2026-10-31 00:35:56 +01:00
evgeny de600c56e9 Bind BlueZ discovery and characteristic selection to node service UUIDs 2026-10-31 00:35:23 +01:00
evgeny 8a5a423da9 Use a single connectable node service advertisement on Windows 2026-10-31 00:33:44 +01:00
evgeny 0b66ec27d2 Discover and select Android BLE peers by their service UUID 2026-10-31 00:32:26 +01:00
evgeny 1e4fca0b25 Encode BLE node identity in versioned GATT service UUIDs 2026-10-31 00:31:23 +01:00
evgeny 56a24c589f Document confirmed Windows beacon and GATT addressing mismatch 2026-10-31 00:27:42 +01:00
evgeny ea98964a89 Log BLE endpoint connectability before Android GATT attempts 2026-10-31 00:23:37 +01:00
evgeny c200fd0cf2 Record verified invitation fixes for rotated addresses and reused MTU 2026-10-31 00:00:53 +01:00
evgeny 79064380cb Document verified BLE bootstrap protocol and frame contracts 2026-10-31 00:00:36 +01:00
evgeny 6bb9a9c14d Verify challenge retries keep the original opening deadline 2026-10-31 00:00:15 +01:00
evgeny 01af2df02b Accept full GATT RX when reused ACL has unknown TX MTU 2026-10-30 23:58:52 +01:00
evgeny 3124c82bd4 Add reproducible hardware invitation delivery probe 2026-10-30 23:57:29 +01:00
evgeny 563203056d Cover private address rotation and unrelated connected peers 2026-10-30 23:54:27 +01:00
evgeny 6c947ac057 Reuse connected BlueZ peer across private address rotation 2026-10-30 23:53:59 +01:00
evgeny e25a8464f2 Bound challenge replacement and test large profiles and cancellation 2026-10-30 23:46:00 +01:00
evgeny 56367d4aef Adapt JOIN scheduler fixture to explicit authenticated routes 2026-10-30 23:42:05 +01:00
evgeny 616ca3ba99 Exercise authenticated BLE JOIN against tampering and replay 2026-10-30 23:41:18 +01:00
evgeny a5d7833e16 Test invitation bootstrap without IP and independent INVITE frame limits 2026-10-30 23:40:56 +01:00
evgeny e88de767ac Release pending bootstrap routes on channel deletion and expiry 2026-10-30 23:40:21 +01:00
evgeny 8dfb9d373f Close cancelled bootstrap sessions and permit fresh bounded retries 2026-10-30 23:37:34 +01:00
evgeny ad8e05c823 Build BLE join carrier in Android native client 2026-10-30 23:36:19 +01:00
evgeny 38c1287b45 Connect BLE bootstrap lifecycle to the shared chat JOIN carrier 2026-10-30 23:36:19 +01:00
evgeny a290234f8a Implement bounded authenticated JOIN transport over BLE INVITE 2026-10-30 23:35:28 +01:00
evgeny 135bfe8132 Bound large INVITE frames separately from BLE DATA 2026-10-30 23:34:04 +01:00
evgeny 6344ff2ecb Share JOIN state machine across ETCP and authenticated carriers 2026-10-30 23:33:57 +01:00
evgeny 8a0cc6f5e1 Add scoped authenticated carrier interface for chat joins 2026-10-30 23:32:47 +01:00
evgeny 44c796a72f Define authenticated BLE join bootstrap architecture 2026-10-30 23:32:26 +01:00
evgeny f40f2cba71 Record BLE join bootstrap deadlock after delivered invitation 2026-10-30 23:23:31 +01:00
evgeny a50af06639 Record BLE invitation diagnosis and remaining initial ACL timeout 2026-10-30 23:19:53 +01:00
evgeny ce89fd1e2c Clarify BLE delivery failures and document connection reuse 2026-10-30 23:18:25 +01:00
evgeny 920ea7ae2c Report failed BLE invitation delivery without success wording 2026-10-30 23:18:13 +01:00
evgeny 13094ae7d6 Reuse connected BlueZ GATT before requesting another bearer 2026-10-30 23:16:15 +01:00
evgeny eafa1297dd Fix WinRT test operation interface conversion 2026-10-30 23:06:55 +01:00
evgeny ca2bebcbd3 Document incoming BLE tuning and refine cancellation test 2026-10-30 23:05:52 +01:00
evgeny 2902602d7f Tune incoming Windows BLE connections for throughput 2026-10-30 23:05:36 +01:00
evgeny 3b9f503ef3 Record completed link admission checks and the separate invitation listener issue 2026-10-30 22:53:57 +01:00
evgeny 89829ca9b6 Describe admission policy as a property of the Bluetooth link 2026-10-30 22:50:45 +01:00
evgeny eda5d99530 Test link-local rejection and unrestricted sockets on shared connections 2026-10-30 22:50:23 +01:00
evgeny 16b1003710 Finish removing connection-level policy arguments 2026-10-30 22:50:12 +01:00
evgeny 5eb0701a41 Keep connection construction independent from link admission policy 2026-10-30 22:50:12 +01:00
evgeny 8d6aef37da Keep connection construction independent from link admission policy 2026-10-30 22:50:11 +01:00
evgeny 510dbc2e15 Keep connection construction independent from link admission policy 2026-10-30 22:50:11 +01:00
evgeny e09a3f9052 Keep connection construction independent from link admission policy 2026-10-30 22:50:11 +01:00
evgeny 2c1ba2b1c0 Keep connection construction independent from link admission policy 2026-10-30 22:50:10 +01:00
evgeny a5299749fb Keep connection construction independent from link admission policy 2026-10-30 22:50:10 +01:00
evgeny dcc7e2f8d7 Make authenticated known-key admission strictly local to each link 2026-10-30 22:49:59 +01:00
evgeny fd05e13525 Remove peer admission policy from shared ETCP connections 2026-10-30 22:49:59 +01:00
evgeny 847fedeac7 Verify encrypted UTUN socket handshakes on BLE-origin shared connections 2026-10-30 22:47:39 +01:00
evgeny 9e01b910ce Document socket policy isolation and prepare native handshake regression 2026-10-30 22:47:14 +01:00
evgeny 80e85bbec6 Keep UTUN socket admission independent from shared BLE connection defaults 2026-10-30 22:46:46 +01:00
evgeny 20e0f6581a Reject restricted paths on existing connections without closing other transports 2026-10-30 22:43:35 +01:00
evgeny 6a7940450e Clarify constructor admission requirements and keep helper below includes 2026-10-30 22:42:50 +01:00
evgeny 6d9ef7383c Recheck peer admission during session handshake and document BLE policy 2026-10-30 22:42:02 +01:00
evgeny 8d92144a5a Test known-key admission, revoked members and unknown invitation-only peers 2026-10-30 22:41:13 +01:00
evgeny ed98ce169e Apply known-peer policy to desktop BLE while keeping explicit hardware probes 2026-10-30 22:40:16 +01:00
evgeny 612b263891 Keep unknown BLE keys in invitation-only mode before ETCP admission 2026-10-30 22:39:59 +01:00
evgeny 3af6ff4961 Specify explicit admission policy in existing ETCP constructors 2026-10-30 22:39:38 +01:00
evgeny 78613d62b5 Specify explicit admission policy in existing ETCP constructors 2026-10-30 22:39:38 +01:00
evgeny 0ff1dc4f66 Specify explicit admission policy in existing ETCP constructors 2026-10-30 22:39:37 +01:00
evgeny 091a1dc053 Specify explicit admission policy in existing ETCP constructors 2026-10-30 22:39:37 +01:00
evgeny 113949083b Specify explicit admission policy in existing ETCP constructors 2026-10-30 22:39:37 +01:00
evgeny 42bb813ee5 Specify explicit admission policy in existing ETCP constructors 2026-10-30 22:39:37 +01:00
evgeny 0850a52180 Check known peer keys after authenticated transport handshake before UP 2026-10-30 22:39:09 +01:00
evgeny 90f70f2b72 Preserve per-link admission policy for shared ETCP connections 2026-10-30 22:38:52 +01:00
evgeny afa834a02d Require known peer admission as an ETCP connection creation policy 2026-10-30 22:38:51 +01:00
evgeny 14e61c68ce Keep known-peer admission policy in the topology module 2026-10-30 22:38:36 +01:00
evgeny 2d054591d5 Validate peer keys against full active group member records 2026-10-30 22:38:36 +01:00
evgeny 8f28adeb0f Record missing BLE incoming group-member admission checks 2026-10-30 22:32:52 +01:00
evgeny 541325c17a Explain BLE advertisement visibility in Android settings 2026-10-30 22:27:51 +01:00
evgeny 55a6abfac5 Explain Bluetooth group connections and unrestricted invitations 2026-10-30 22:26:43 +01:00
evgeny 85be60d716 Enable the three Android BLE connection flags by default 2026-10-30 22:26:43 +01:00
evgeny bb99796140 Verify monitoring enable, disable and endpoint validation contracts 2026-10-30 22:23:15 +01:00
evgeny 168f3e9d97 Add a default-off monitoring switch and conditional endpoint fields 2026-10-30 22:23:15 +01:00
evgeny f6009d3070 Persist optional Android monitoring endpoints into native configuration 2026-10-30 22:23:15 +01:00
evgeny baf58a7971 Record missing Android monitoring configuration wiring 2026-10-30 22:18:42 +01:00
evgeny 6db34b558a Remove the unused Android node listen port preference 2026-10-30 22:18:42 +01:00
evgeny 5bb0df82b6 Clarify Android developer settings labels and warning 2026-10-30 22:18:42 +01:00
evgeny 8f1ede0344 Show the selected Android settings section in the header 2026-10-30 22:12:20 +01:00
evgeny d4a2dac903 Reuse the chat portable radio icon in Android settings 2026-10-30 22:11:55 +01:00
evgeny bd453311ac Use labeled icons for Android settings section tabs 2026-10-30 22:09:05 +01:00
evgeny 9f59e0968e Update call UI checks and document the unified diagnostics window 2026-10-30 21:51:50 +01:00
evgeny b08161b055 Unify call graphs and metrics behind the Diagnostics action 2026-10-30 21:51:32 +01:00
evgeny ad21c49d8f Place call graph canvas alongside a resizable diagnostic text pane 2026-10-30 21:51:10 +01:00
evgeny aa9c3beece Clarify transport summary counters and initial diagnostic baseline 2026-10-30 21:50:11 +01:00
evgeny 2de735f3ff Include route retransmissions and window without creating diagnostic channels 2026-10-30 21:49:15 +01:00
evgeny da1b4839ea Verify diagnostic cadence, filtering and full buffer log delivery 2026-10-30 21:48:43 +01:00
evgeny 97934de381 Test independent log intervals and document diagnostic units 2026-10-30 21:48:17 +01:00
evgeny 5bc6350cc0 Report call route queues and ACK progress at 200ms cadence 2026-10-30 21:47:55 +01:00
evgeny 110b71d17f Share the diagnostic cadence and clamp concurrent pull timestamp skew 2026-10-30 21:47:55 +01:00
evgeny 15d44165da Log audio buffer health every 200ms outside playback locks 2026-10-30 21:47:15 +01:00
evgeny ff992bcd40 Expose bounded audio log snapshots without consuming playback events 2026-10-30 21:46:53 +01:00
evgeny d05aed35f9 Collect exact playback intervals independently from graph history 2026-10-30 21:46:53 +01:00
evgeny 2cd3f966b2 Document fresh CCC preparation and finalize reconnect regression 2026-10-30 21:43:26 +01:00
evgeny 752a3a7d95 Prepare WinRT subscriptions afresh and test BlueZ session replacement 2026-10-30 21:41:38 +01:00
evgeny 68444ef192 Fix BLE subscription reset and incoming session replacement on reconnect 2026-10-30 21:41:13 +01:00
evgeny 88436cde0e Package audio history headers and record outdated call fixtures 2026-10-30 21:31:50 +01:00
evgeny 476ab1b840 Preserve recorded traffic rates as the history window advances 2026-10-30 21:30:52 +01:00
evgeny 8e6efd2b00 Keep graph extrema readable and validate accepted packet counters 2026-10-30 21:27:46 +01:00
evgeny 015e8b75d7 Localize Android audio history graph labels and units 2026-10-30 21:25:11 +01:00
evgeny ca7d64ac2b Add stacked live audio graphs to the Android call screen 2026-10-30 21:25:11 +01:00
evgeny 141148611f Expose shared audio and transmission history to Android 2026-10-30 21:25:11 +01:00
evgeny 355604a862 Document graph measurement boundaries and improve label contrast 2026-10-30 21:23:54 +01:00
evgeny b760cef460 Test audio graph lifecycle, throughput path changes and accepted send accounting 2026-10-30 21:22:12 +01:00
evgeny ef0af0dd5e Localize desktop audio graph labels and measurement units 2026-10-30 21:18:30 +01:00
evgeny 2406ff0f11 Open audio graphs from the desktop call controls 2026-10-30 21:18:19 +01:00
evgeny d1897bd6e6 Add stacked desktop audio history, queue, throughput and histogram plots 2026-10-30 21:18:01 +01:00
evgeny 9d88f63062 Calculate path-aware ETCP throughput over a sliding one second window 2026-10-30 21:15:21 +01:00
evgeny 490515b7c2 Capture call path traffic alongside aggregate transmission queues 2026-10-30 21:14:05 +01:00
evgeny 65f0c62a23 Expose selected Router path traffic counters without borrowing live connections 2026-10-30 21:13:57 +01:00
evgeny 055dd3ada0 Count accepted ETCP wire bytes per connection including control and retries 2026-10-30 21:13:57 +01:00
evgeny 9c8088ac8d Record aggregate Router and transport histories and verify weighted audio statistics 2026-10-30 21:12:20 +01:00
evgeny 1f974e8244 Expose shared call history snapshots to frontends and queue sampling 2026-10-30 21:11:51 +01:00
evgeny 1b566ddbe5 Collect call audio buffer history independently of visible diagnostics 2026-10-30 21:11:18 +01:00
evgeny 09199cc46b Add bounded shared audio history and time weighted histogram snapshots 2026-10-30 21:11:05 +01:00
evgeny e43f95ea83 Keep startup defaults and reset reserve snapshots consistent 2026-10-30 20:05:23 +01:00
evgeny a7bb72a0b7 Replenish playout reserve smoothly and account for packet cadence in delay control 2026-10-30 20:03:49 +01:00
evgeny 0c20766cfe Gate startup on published PCM and test recovery beyond the initial reserve 2026-10-30 19:57:25 +01:00
evgeny b092e09b43 Adapt call batching to queue pressure and verify protected audio startup 2026-10-30 19:54:58 +01:00
evgeny 1960377e5c Prime desktop speech PCM before enabling device consumption 2026-10-30 19:52:56 +01:00
evgeny a3a54af0fe Define protected call startup reserve and explicit queued renderer readiness 2026-10-30 19:52:40 +01:00
evgeny dff64e2871 Account for the completed audio batch in the video barrier fixture 2026-10-30 19:31:29 +01:00
evgeny efd80949cd Document adaptive full batches and Router readiness ownership 2026-10-30 19:30:12 +01:00
evgeny 215f744bbe Verify adaptive batch targets and reject partial sends on a free transport 2026-10-30 19:29:06 +01:00
evgeny 6ae080d417 Require the adaptive frame count before requesting or using a Router slot 2026-10-30 19:28:22 +01:00
evgeny ee5c258b3c Preserve adaptive audio batch target without partial-packet deadlines 2026-10-30 19:28:21 +01:00
evgeny e598568652 Trigger actual lower queue drain in producer readiness test 2026-10-30 19:26:24 +01:00
evgeny ffa1208cb6 Make producer window test independent of min-RTT probing 2026-10-30 19:25:11 +01:00
evgeny 20b3116e7c Cover lazy Router producers and audio batching under backpressure 2026-10-30 19:24:24 +01:00
evgeny 74eb935589 Remove obsolete audio batch delay controller 2026-10-30 19:21:46 +01:00
evgeny e3764991d4 Build call audio batches only when Router grants a send slot 2026-10-30 19:21:29 +01:00
evgeny 273eabbc6e Add cancellable Router send requests at transport readiness 2026-10-30 19:20:17 +01:00
evgeny 2d4b2f10a6 Keep BLE candidate monitoring separate from IP probes 2026-10-30 19:15:17 +01:00
evgeny ca04b098f8 Keep all call streams alive during router recovery and verify RTT ambiguity handling 2026-10-30 18:53:53 +01:00
evgeny 34cbdc3cde Test conservative router recovery and recover lost receive-resume acknowledgements 2026-10-30 18:52:25 +01:00
evgeny 8f5882081f Separate router DATA recovery timers and add adaptive retransmission backoff 2026-10-30 18:49:47 +01:00
evgeny d1886be6f4 Request maximum BLE advertising power and display radio power status 2026-10-30 18:15:37 +01:00
evgeny 8a02704f8b Document BLE startup sequencing and honor publication deadline 2026-10-30 17:55:26 +01:00
evgeny e81fe7030a Cover initial BLE publication and preserve radio diagnostics 2026-10-30 17:54:14 +01:00
evgeny 77979c4058 Start Windows BLE publisher before GATT and sequence updates 2026-10-30 17:52:42 +01:00
evgeny 4eefe43053 Pass desktop BLE identity to transport before startup 2026-10-30 17:50:32 +01:00
evgeny df23626c47 Remove system stall investigation from task list 2026-10-30 17:39:09 +01:00
evgeny 3eb9c46985 Add configurable Opus burst batches for radio transmission 2026-10-30 17:38:43 +01:00
evgeny 049c8ef155 Improve BLE call batching, startup buffering and diagnostics 2026-10-30 16:44:52 +01:00
evgeny 0afccfb624 Probe Windows BLE publisher startup before GATT advertising 2026-10-30 12:55:11 +01:00
evgeny 77edf2bcf7 Show BLE receive counts below Android device nicknames 2026-10-30 12:48:18 +01:00
evgeny 6e53490cdd Add Android text for BLE broadcast receive counts 2026-10-30 12:48:18 +01:00
evgeny 7cd78e9210 Verify BLE neighbor counters without changing invitation fixtures 2026-10-30 12:47:51 +01:00
evgeny 184b02b342 Show per-device BLE receive counts in desktop rows 2026-10-30 12:46:27 +01:00
evgeny 49cbb7e148 Keep BLE counters tied to neighbor table entries 2026-10-30 12:45:56 +01:00
evgeny d86599995c Count received BLE advertisements over each neighbor lifetime 2026-10-30 12:45:18 +01:00
evgeny 0907395779 Document Windows 1809 advertising probe stop acknowledgement 2026-10-30 12:39:42 +01:00
evgeny 8aa4330c72 Handle requested GATT stop in Windows advertising probe 2026-10-30 12:39:17 +01:00
evgeny ace0ce3e85 Test and document Windows BLE radio status diagnostics 2026-10-30 12:18:19 +01:00
evgeny 3e1d1ddbfd Add Windows BLE advertising resource diagnostics 2026-10-30 12:17:19 +01:00
evgeny 4083865c6f Add the legacy BLE example as a reference 2026-10-30 12:12:53 +01:00
evgeny e6c35bc858 Compact Android Bluetooth devices into two-line rows 2026-10-30 12:07:30 +01:00
evgeny 22d8d872c4 Translate Android Bluetooth device list status messages 2026-10-30 11:54:11 +01:00
evgeny 1cbf63e053 Add the Android nearby Bluetooth device list 2026-10-30 11:54:11 +01:00
evgeny 050b2f6d05 Batch Windows installer staging and license queries 2026-10-30 11:44:06 +01:00
evgeny f87f70489a Show Bluetooth addresses in the desktop device list 2026-10-30 11:26:29 +01:00
evgeny eeb2373599 Keep BLE discovery summaries at ten-second intervals 2026-10-30 11:21:04 +01:00
evgeny 2a19c08d62 Report WinRT scan filters and prolonged publisher waiting 2026-10-30 11:11:40 +01:00
evgeny cd62ea0b6e Log BLE discovery decisions and cumulative receive counters 2026-10-30 11:09:54 +01:00
evgeny f7f3636032 Expose precise BLE identity rejection reasons 2026-10-30 11:08:29 +01:00
evgeny 359c6bc843 Reuse PE cache during packaging and test installer completeness 2026-10-30 11:00:08 +01:00
evgeny 0bee366d6b Share cached PE imports and architecture with Windows packaging 2026-10-30 10:59:04 +01:00
evgeny 8617405464 Merge origin/master preserving BLE wire v4 and Windows 1809 support 2026-10-30 10:55:16 +01:00
evgeny 1e6a766347 Cache Windows ChatGUI runtime imports and deployment 2026-10-30 10:52:51 +01:00
evgeny 7d0c394091 Document Windows 1809 BLE cache lookup and diagnostics 2026-10-30 10:31:25 +01:00
evgeny 64770b579d Support WinRT BLE discovery and connection on Windows 1809 2026-10-30 10:30:22 +01:00
evgeny e1e3c9cfde Document unconfirmed BLE acknowledgements and measured latency limits 2026-10-30 04:54:47 +01:00
evgeny 51795a558c Log invalid BLE probe payload and pacing arguments 2026-10-30 04:48:37 +01:00
evgeny 51d2231ac7 Keep BLE probe packet cadence on absolute deadlines 2026-10-30 04:42:24 +01:00
evgeny fc020f4f05 Measure BLE ETCP echo latency with paced small packets 2026-10-30 04:39:05 +01:00
evgeny 09e045a45d Use unconfirmed BLE ACK writes and notifications on Android 2026-10-30 04:39:05 +01:00
evgeny 452ab50f9e Switch WinRT ACK delivery and advertise BLE wire version four 2026-10-30 04:35:42 +01:00
evgeny d0df49446c Send BlueZ flow acknowledgements without ATT responses 2026-10-30 04:35:12 +01:00
evgeny e0076d5d10 Repeat cumulative BLE acknowledgements after unreliable delivery 2026-10-30 04:34:54 +01:00
evgeny 008bafc18a Cover lost cumulative BLE acknowledgements with full duplex windows 2026-10-30 04:34:10 +01:00
evgeny f4bcc6eae9 Log BLE packet sequences and acknowledgements in debug category 2026-10-30 04:31:55 +01:00
evgeny 97b18caa1f Revert "Log the exact reason and lifetime of rejected call invites"
This reverts commit 55637c296f80f016f0a29f54aaa7aaf742b92443.
2026-10-30 04:31:55 +01:00
evgeny 6a2e552194 Log the exact reason and lifetime of rejected call invites 2026-10-30 04:31:55 +01:00
evgeny 93672ae95e Fix desktop BLE mock signature for wire channels 2026-10-29 22:53:35 +01:00
evgeny ae1d149545 Merge branch 'master' of http://git.syqiq.tech/jeka/utun2 2026-10-29 22:43:06 +01:00
evgeny 33a3774938 Require BLE probe publication and document WinRT diagnostics 2026-10-29 22:42:36 +01:00
evgeny dd80f589fa Record successful BLE ACK loads in both connection roles 2026-10-29 22:39:54 +01:00
evgeny 4a7f3253f6 Test WinRT BLE exception isolation and pending shutdown 2026-10-29 22:39:15 +01:00
evgeny dc70174af9 Preserve WinRT BLE event context and diagnose API failures 2026-10-29 22:38:08 +01:00
evgeny 552f7b31b0 Record ACK scheduling regression and successful desktop load 2026-10-29 22:36:14 +01:00
evgeny b1a272fa23 Clarify BLE ACK spacing after local completion 2026-10-29 22:33:17 +01:00
evgeny d5505c054f Reserve the ACK interval after completion for payload traffic 2026-10-29 22:31:17 +01:00
evgeny c52afe4f41 Give DATA a slot between slow cumulative BLE ACKs 2026-10-29 22:29:46 +01:00
evgeny b7e0b1f12c Reproduce DATA starvation behind slow BLE ACK completion 2026-10-29 22:29:32 +01:00
evgeny c83b30aa0b Document BLE v3 ACK framing and bounded remote credit 2026-10-29 22:26:34 +01:00
evgeny 6338a2aae1 Open both fake GATT endpoints before delivering HELLO 2026-10-29 22:22:35 +01:00
evgeny 358c3093dd Refresh WinRT subscriptions before the first incoming value 2026-10-29 22:21:51 +01:00
evgeny fabf0c1663 Reject BLE values before all mandatory subscriptions 2026-10-29 22:21:12 +01:00
evgeny 4016e6b73c Include BLE credit events in the existing wire trace 2026-10-29 22:19:43 +01:00
evgeny c43726c17d Verify BLE ACK timeout independently of local completion 2026-10-29 22:17:57 +01:00
evgeny b31b772e66 Delay remote ACK delivery independently in the BLE fixture 2026-10-29 22:16:46 +01:00
evgeny 46f2137f06 Keep BLE fault injection correct with prefixed fragments 2026-10-29 22:16:08 +01:00
evgeny d33b67d87c Test BLE remote credit, ACK timing, duplex and ID wrap 2026-10-29 22:15:32 +01:00
evgeny 85977d97e0 Verify mandatory ACK subscriptions and addressed BlueZ ACKs 2026-10-29 22:13:46 +01:00
evgeny d4182c22cd Connect the ACK characteristic to Android GATT and JNI 2026-10-29 22:13:46 +01:00
evgeny e7adcbe139 Support the BLE ACK characteristic in WinRT 2026-10-29 22:11:46 +01:00
evgeny dd1769ee4c Adapt BLE identity and ETCP fixtures to the ACK profile 2026-10-29 22:10:40 +01:00
evgeny cecdbbe1d7 Add the mandatory ACK characteristic to BlueZ 2026-10-29 22:10:24 +01:00
evgeny 4e38536a55 Bound BLE DATA flight with cumulative 16-bit ACKs 2026-10-29 22:09:12 +01:00
evgeny be0dff7b2c Define the BLE ACK wire channel and fixed flight budget 2026-10-29 22:08:29 +01:00
evgeny e194535b25 Record RTO validation and remaining BLE throughput work 2026-10-29 21:39:31 +01:00
evgeny 635e1726e6 Document BLE readiness fixes and remaining HCI queue delay 2026-10-29 21:37:40 +01:00
evgeny 55bb052406 Model accepted sends in the ETCP lifecycle fixture 2026-10-29 21:34:02 +01:00
evgeny 0f2794cd51 Format the RTT growth regression cases consistently 2026-10-29 21:25:46 +01:00
evgeny a9bec81328 Let ETCP retransmission timeouts cover measured RTT above one second 2026-10-29 21:18:52 +01:00
evgeny 5b2e11337c Use the native BLE discovery version in Android scan filters 2026-10-29 20:47:48 +01:00
evgeny 285a242d2a Version BLE discovery for unacknowledged DATA compatibility 2026-10-29 20:39:20 +01:00
evgeny b5fb6b0f4d Ignore cached BlueZ advertisements when discovering live BLE peers 2026-10-29 20:29:55 +01:00
evgeny 8081f94ebe Record BLE negotiation evidence and retry pre-transfer radio connections 2026-10-29 20:29:09 +01:00
evgeny 05d78c9960 Add a controlled Android scan pause to the manual BLE probe 2026-10-29 20:14:51 +01:00
evgeny 8ab25c1389 Request high BLE priority for incoming Android links on the shared ACL 2026-10-29 19:58:40 +01:00
evgeny 7dab663b93 Preserve incoming disconnect handling and exercise resolved-service notification 2026-10-29 19:50:44 +01:00
evgeny 51621e6240 Wait for resolved BlueZ services before opening cached GATT characteristics 2026-10-29 19:45:27 +01:00
evgeny 083495986e Document HCI queue delays and explain incompatible GATT properties 2026-10-29 19:10:13 +01:00
evgeny b5b522b732 Log ETCP control submission failures and WinRT error codes 2026-10-29 19:00:53 +01:00
evgeny c5711b5974 Preserve Android BLE failure status and callback diagnostics 2026-10-29 19:00:11 +01:00
evgeny de6e2ada0c Report BLE frame gaps and preserve BlueZ I/O errors 2026-10-29 18:56:50 +01:00
evgeny 8811276ca8 Trace BLE frame delivery and authenticated packet dispatch 2026-10-29 18:46:00 +01:00
evgeny 33b4f0acc8 Record BLE throughput results and harden the hardware probe 2026-10-29 18:38:11 +01:00
evgeny 3def3f5af2 Use unacknowledged BLE DATA and request faster connections 2026-10-29 18:28:05 +01:00
evgeny 9382abb6e6 Fix Windows system library dependencies for uasync 2026-10-29 17:46:18 +01:00
evgeny 5152b17114 Fix BLE link display and remove obsolete tool projects 2026-10-29 17:10:39 +01:00
evgeny f84622966e Add BLE ETCP links and GATT invitations for desktop and Android
Attach packet drivers to initially empty ETCP connections. Share BLE neighbor
tracking and group fallback between desktop and Android in cgathui_common.

Deliver join links through a dedicated Write/Indicate characteristic with
independent fragmentation queues, application acknowledgements, deduplication
and bounded retries. Merge LAN/BLE discovery and add a separate Bluetooth
invitation reception setting to both clients.

Validation: 230 core tests, BLE transport/BlueZ/UI tests, ASAN/UBSAN,
Linux GUI and Android builds, and Windows backend cross-compilation.
Physical Android/Linux invitation exchange passed with either GATT initiator.
The Android-initiated run also verified all 32 ETCP packets of 1500 bytes;
the desktop-initiated load run reached 7/32 within its 45-second time limit.
2026-10-29 16:41:04 +01:00
evgeny ef6a5673bd Preserve member connection state when its refresh fails 2026-10-29 14:02:25 +01:00
evgeny 05ea602a3a Distinguish failed member-link snapshots from confirmed disconnection 2026-10-29 14:02:25 +01:00
evgeny a4c7899ffb Keep native member query failures distinct from valid empty snapshots 2026-10-29 14:02:25 +01:00
evgeny 0878947e13 Describe Android view-model snapshots and application-owned configuration 2026-10-29 14:00:16 +01:00
evgeny 2460e810d6 Document asynchronous BLE detach and report probe cleanup failures 2026-10-29 13:59:14 +01:00
evgeny 0f03aa8b5c Align Android architecture with serialized lifecycle and Bluetooth ownership 2026-10-29 13:56:57 +01:00
evgeny f1f113a5f2 Describe readiness recovery when a rejected restart retains the core 2026-10-29 13:56:57 +01:00
evgeny 0800fd61a7 Retry failed BLE SDK releases and propagate radio command rejection 2026-10-29 13:54:52 +01:00
evgeny 5410c4c6c6 Retain BLE cleanup ownership until each Android release succeeds 2026-10-29 13:53:22 +01:00
evgeny 6c7f5b7032 Apply Bluetooth flag changes atomically without replacing concurrent selections 2026-10-29 13:53:22 +01:00
evgeny 8dc10bb54f Keep Bluetooth settings writes alive and contain Android launch failures 2026-10-29 13:51:59 +01:00
evgeny ae4f524448 Observe confirmed Bluetooth preferences from the application owner 2026-10-29 13:51:58 +01:00
evgeny 1651d1b870 Document native ownership and reject media creation during core cleanup 2026-10-29 13:50:21 +01:00
evgeny 4a5a8cf057 Keep malformed events and deleted database state out of Android UI 2026-10-29 13:49:57 +01:00
evgeny c5879042fb Validate complete channel event frames before publishing state 2026-10-29 13:49:00 +01:00
evgeny d636a03928 Test restart readiness recovery and explicit UTF-8 database cleanup 2026-10-29 13:39:58 +01:00
evgeny 132e222415 Resume retained core owners and observe unexpected service loss 2026-10-29 13:35:42 +01:00
evgeny 791ff42547 Keep database reset atomic and owned beyond the activity lifecycle 2026-10-29 13:35:42 +01:00
evgeny 665137314a Serialize native lifecycle mutations and renew readiness across restart 2026-10-29 13:35:42 +01:00
evgeny 0568d263e0 Reject fresh radio and publisher owners during core cleanup 2026-10-29 13:35:42 +01:00
evgeny 044ff034a6 Await radio and shared audio release before native core teardown 2026-10-29 13:35:42 +01:00
evgeny ea67b491f9 Show private conversation start failures and test stale confirmation isolation 2026-10-29 13:35:41 +01:00
evgeny 321a2c3ed7 Match private conversation confirmations before opening the requested peer 2026-10-29 13:35:41 +01:00
evgeny 69ae8b57cb Bind private conversation start requests to the worker conversation ID 2026-10-29 13:35:41 +01:00
evgeny c1ad35e152 Persist channel mute consistently and own panel preference changes 2026-10-29 13:35:41 +01:00
evgeny fb696d0d56 Report rejected core actions and log nickname write outcomes 2026-10-29 13:35:41 +01:00
evgeny 3aecc095ff Return queue rejection for invite and private conversation requests 2026-10-29 13:35:41 +01:00
evgeny da540627fc Keep accepted commands bound to their instance while restart readiness closes 2026-10-29 13:35:41 +01:00
evgeny f15ca995b7 Close frontend readiness while a restart is pending and retain failed core state 2026-10-29 13:35:41 +01:00
evgeny f50310afed Verify config callback thread attachment and reject truncated database paths 2026-10-29 13:35:41 +01:00
evgeny 20f506fc3c Contain JNI config failures and validate audio result buffers 2026-10-29 13:35:41 +01:00
evgeny af776deed6 Keep member snapshots atomic and verify escaped socket names 2026-10-29 13:35:41 +01:00
evgeny 89a4630477 Build complete network JSON snapshots and verify SQL failure recovery 2026-10-29 13:35:41 +01:00
evgeny 05ab3b8054 Return complete channel snapshots and distinguish database errors from empty history 2026-10-29 13:35:41 +01:00
evgeny 57227b331d Exercise event callback replacement and exceptions on a real JVM 2026-10-29 13:35:41 +01:00
evgeny 2f4cded218 Preserve event callback lifetime and contain JNI delivery exceptions 2026-10-29 13:35:41 +01:00
evgeny 17f79b16cd Run checked JVM string tests with the Android verification tasks 2026-10-29 13:35:41 +01:00
evgeny c0a4beeec4 Verify JNI UTF-8 strings against a real JVM with checked JNI 2026-10-29 13:35:41 +01:00
evgeny 86f0ac7625 Route remaining JNI producers through the core task owner 2026-10-29 13:35:41 +01:00
evgeny 95f0e89567 Read JNI database and live network snapshots in the core worker 2026-10-29 13:35:41 +01:00
evgeny 8614ba5428 Use ordinary UTF-8 across JNI strings and test cancelled media ownership 2026-10-29 13:35:41 +01:00
evgeny 72ee8f2586 Release detached voice and PM file payloads when queued work is cancelled 2026-10-29 13:35:41 +01:00
evgeny 57bfadb04c Retain media request ownership until execution or worker cancellation 2026-10-29 13:35:41 +01:00
evgeny 38ab885609 Expose attachment cancellation as a typed task discard callback 2026-10-29 13:35:41 +01:00
evgeny f731ac340d Serialize bridge command publication and report rejected lifecycle requests 2026-10-29 13:35:41 +01:00
evgeny 8374c60b0e Publish message requests through the worker lifetime owner 2026-10-29 13:35:41 +01:00
evgeny 5a4ddca190 Protect lifecycle producers and leave fatal signals to the platform 2026-10-29 13:35:41 +01:00
evgeny 929df3b6cb Exercise worker request cancellation against real lifecycle teardown 2026-10-29 13:35:41 +01:00
evgeny 8c0c17270e Own frontend tasks through worker teardown and marshal synchronous reads 2026-10-29 13:35:41 +01:00
evgeny d20e112933 Isolate activity cleanup and document startup event ownership 2026-10-29 13:35:41 +01:00
evgeny b8ccd515dd Load startup preferences asynchronously and contain service launch errors 2026-10-29 13:35:41 +01:00
evgeny 013ff93406 Load audio and network settings on IO and document persistent change ownership 2026-10-29 13:35:41 +01:00
evgeny 30648086b4 Contain remaining settings loader failures and remove retired UI scopes 2026-10-29 13:35:41 +01:00
evgeny 828b36f290 Keep failed settings teardown retryable and preserve UI until database stop succeeds 2026-10-29 13:35:41 +01:00
evgeny c5c4d0e588 Load confirmed settings after pending changes and guard invalid audio preferences 2026-10-29 13:35:41 +01:00
evgeny 48564e8ab3 Respect microphone permission callback ownership and test settings disposal 2026-10-29 13:35:19 +01:00
evgeny b086750cf3 Persist audio settings before runtime updates and release hidden microphone tests 2026-10-29 13:35:19 +01:00
evgeny eb837206c3 Own radio settings changes and preserve observed state after IO failures 2026-10-29 13:35:19 +01:00
evgeny 61bdf4a6df Retain observed settings through read failures and retry without default resets 2026-10-29 13:35:19 +01:00
evgeny e8aeaaf365 Apply developer settings only after accepted persistence completes 2026-10-29 13:35:19 +01:00
evgeny a9495de90f Keep settings persistence alive after navigation and guard initial preference loading 2026-10-29 13:35:19 +01:00
evgeny 87166db832 Test settings persistence ownership, ordering and failure isolation 2026-10-29 13:35:19 +01:00
evgeny a95245e272 Own ordered settings changes independently of the Compose screen 2026-10-29 13:35:19 +01:00
evgeny 299518e866 Preserve confirmed settings and manual socket choices after failures 2026-10-29 13:35:19 +01:00
evgeny de907c697b Match temporary IPv6 flags using canonical address bytes 2026-10-29 13:35:19 +01:00
evgeny 268e8794ab Document process lifetime voice ownership and core shutdown prerequisites 2026-10-29 13:35:19 +01:00
evgeny d0d63c1d4b Keep voice cleanup independent of caller cancellation and stop playback promptly 2026-10-29 13:35:19 +01:00
evgeny 48a20cda8c Reject new capture while an IO teardown holds its lifecycle lock 2026-10-29 13:35:19 +01:00
evgeny c7356d2a5b Wait for asynchronous voice cleanup acknowledgement in lifecycle regression test 2026-10-29 13:35:19 +01:00
evgeny 5ee87c535b Avoid capture-lock acquisition while rolling back a playback worker launch 2026-10-29 13:35:19 +01:00
evgeny 3f2cc2abb3 Verify call preparation waits for voice cleanup and document process barriers 2026-10-29 13:35:19 +01:00
evgeny 41ea2afaaa Verify explicit native cancellation failure and document independent audio ownership 2026-10-29 13:35:19 +01:00
evgeny a9099a5ea7 Separate playback controls from blocked capture cleanup and gate stopping cores 2026-10-29 13:35:19 +01:00
evgeny b25766ae5a Test retained voice resources, decoder failures and nonblocking disposal 2026-10-29 13:35:19 +01:00
evgeny bb08b20e58 Wait for voice recording and playback release before call signalling 2026-10-29 13:35:19 +01:00
evgeny a85d2cc8c7 Retain voice resources after ViewModel disposal and block premature core teardown 2026-10-29 13:35:19 +01:00
evgeny 85af6f5b87 Deliver app events once and isolate failures in independent consumers 2026-10-29 13:35:19 +01:00
evgeny 6916575380 Contain headless foreground, notification and teardown failures 2026-10-29 13:34:26 +01:00
evgeny d7fb8568b2 Retry core shutdown until pending frontend resources are released 2026-10-29 13:34:26 +01:00
evgeny 1529dfd04b Document camera finalization ownership and isolate late SDK diagnostics 2026-10-29 13:34:26 +01:00
evgeny 8dd8dc96d7 Verify recorded tracks and handle camera permission and SDK cleanup failures 2026-10-29 13:34:26 +01:00
evgeny 9ac6e4a2f4 Compile track inspection and its SDK boundary in video lifecycle tests 2026-10-29 13:34:26 +01:00
evgeny fca68080bc Own recorded video track inspection until extractor release succeeds 2026-10-29 13:34:26 +01:00
evgeny 8a1c77793d Keep camera caches until finalization and contain recording control failures 2026-10-29 13:34:26 +01:00
evgeny 871acd9383 Test camera writer completion, failed close, binding cleanup and cache transfer 2026-10-29 13:34:26 +01:00
evgeny 09386ee392 Retain camera recording and cache ownership until writer completion 2026-10-29 13:34:26 +01:00
evgeny 3ae8d12434 Keep submission IDs unique across ViewModels and document native cache transfer 2026-10-29 13:34:26 +01:00
evgeny ab6a10026e Verify PM voice receipts and document composer and cache ownership 2026-10-29 13:34:26 +01:00
evgeny 3f0c89a6a3 Verify real PM media commit failures, exact receipts and source cleanup 2026-10-29 13:34:26 +01:00
evgeny 6eb865242b Test video submission validation and retriever cleanup acknowledgements 2026-10-29 13:34:26 +01:00
evgeny 3df64b6744 Use voice commit receipts for both conversation types and document ownership 2026-10-29 13:34:26 +01:00
evgeny dad127d770 Wait for committed PM media and retain native ownership of accepted cache files 2026-10-29 13:34:26 +01:00
evgeny 2dbc45e63d Transfer Android ordinary attachment caches to the shared media worker 2026-10-29 13:34:26 +01:00
evgeny ce80fbcd10 Expose committed PM file results through Android JNI 2026-10-29 13:34:26 +01:00
evgeny d6eed3e9c9 Specify receipt policy in native DM media callers 2026-10-29 13:34:26 +01:00
evgeny 31e461dca2 Carry voice PM receipts and document shared media completion semantics 2026-10-29 13:34:26 +01:00
evgeny e943879c50 Carry Android photo and video request IDs through PM preparation 2026-10-29 13:34:26 +01:00
evgeny 4fd5ebf57a Acknowledge PM media submissions after local commit or preparation failure 2026-10-29 13:34:26 +01:00
evgeny dae19c06d7 Preserve composer commit receipts and finish message batches after rotation 2026-10-29 13:34:26 +01:00
evgeny 47e997df15 Own composed message batches and receipts beyond Activity lifetime 2026-10-29 13:34:26 +01:00
evgeny a0c8d5490c Test atomic JSON snapshots, failure diagnostics and subsequent recovery 2026-10-29 13:34:26 +01:00
evgeny 3eb7f8b0e6 Preserve UI snapshots after parse failure and ignore superseded queries 2026-10-29 13:34:26 +01:00
evgeny 7d67213847 Handle unavailable channel snapshots in Android media consumers 2026-10-29 13:34:26 +01:00
evgeny 4fbb825b9b Reject partial Android repository snapshots and distinguish query failures 2026-10-29 13:34:26 +01:00
evgeny e942190b9f Allow call teardown to defer optional pause when reporter owns the output 2026-10-29 13:34:26 +01:00
evgeny 1097c24d91 Document call signalling barriers and isolate routing diagnostic failures 2026-10-29 13:34:26 +01:00
evgeny 5dffdee8ff Document nonblocking audio cleanup and keep lifecycle tests on main 2026-10-29 13:34:25 +01:00
evgeny ff1f7a4bb8 Keep call audio main thread responsive while device workers are blocked 2026-10-29 13:34:25 +01:00
evgeny 314b77242f Test call route persistence and busy outcome failure isolation 2026-10-29 13:34:25 +01:00
evgeny 236dbd3e84 Contain call notification and route persistence failures 2026-10-29 13:34:25 +01:00
evgeny 7e328b3908 Test rejected call signalling and deferred hangup recovery 2026-10-29 13:34:25 +01:00
evgeny 38e2cc4336 Retain failed call end commands until the worker accepts them 2026-10-29 13:34:25 +01:00
evgeny 1600f5710c Return explicit queue results for call signalling commands 2026-10-29 13:34:25 +01:00
evgeny eccf5f451c Use explicit DM test headers and clarify proximity lifecycle text 2026-10-29 13:34:25 +01:00
evgeny f5405cdb3d Verify Android DM commit results and document sensor cleanup retry 2026-10-29 13:34:25 +01:00
evgeny 96166cd3a7 Keep PM drafts until the core confirms persistence 2026-10-29 13:34:25 +01:00
evgeny d5a1e4b962 Request DM persistence acknowledgement and send canonical UTF-8 2026-10-29 13:34:25 +01:00
evgeny c5d8307697 Retain proximity registrations after partial SDK failures 2026-10-29 13:34:25 +01:00
evgeny aa9ca53468 Clarify member update acknowledgement and suppress duplicate downloads 2026-10-29 13:34:25 +01:00
evgeny e0e97f1c7a Guard media previews and cancel interrupted voice recording gestures 2026-10-29 13:34:25 +01:00
evgeny 236aeae828 Bound video thumbnails and share retriever cleanup ownership 2026-10-29 13:34:25 +01:00
evgeny d3e83c3c1a Guard member editor actions and display unsigned node identifiers 2026-10-29 13:34:25 +01:00
evgeny 2c2d4f3d9d Validate restored attachment recipients and document conversation UI 2026-10-29 13:34:25 +01:00
evgeny 98d4f903a0 Report channel file export failures and preserve attachment choices 2026-10-29 13:34:25 +01:00
evgeny 666210c3fb Preserve selected attachment targets and contain composer errors 2026-10-29 13:34:25 +01:00
evgeny 89cf180984 Document local video playback and metadata release contracts 2026-10-29 13:34:25 +01:00
evgeny e18ecda41e Fix video fixture ownership and identify playback resource diagnostics 2026-10-29 13:34:25 +01:00
evgeny 8678ace89b Test local video SDK failures, stale callbacks and release barriers 2026-10-29 13:34:25 +01:00
evgeny 5694f97f12 Add controllable SDK boundaries for local video lifecycle tests 2026-10-29 13:34:25 +01:00
evgeny 7ec46278af Keep video gesture callbacks current and forbid reads during cleanup 2026-10-29 13:34:25 +01:00
evgeny fdecfe1b78 Drive video controls from SDK outcomes and preserve paused playback 2026-10-29 13:34:25 +01:00
evgeny d9661d0f59 Own local video playback resources through confirmed SDK release 2026-10-29 13:34:25 +01:00
evgeny 401edd37b8 Document call view ownership and preserve probe interrupts 2026-10-29 13:34:25 +01:00
evgeny 623344369f Guard call permission results and release video targets idempotently 2026-10-29 13:34:25 +01:00
evgeny c8ecf89424 Handle PM document export failures and stale channel dialogs 2026-10-29 13:34:25 +01:00
evgeny 096c1ee2a8 Report probe worker failures and attempt independent SDK cleanup 2026-10-29 13:34:25 +01:00
evgeny 6f5850b9ca Reject empty codec probe runs and preserve decoder cleanup 2026-10-29 13:34:25 +01:00
evgeny 9383a68f17 Release failed member snapshot requests and validate deletion frames 2026-10-29 13:34:25 +01:00
evgeny 36af8d077f Handle stream capture permission failures and document preview release 2026-10-29 13:34:25 +01:00
evgeny 45d1b50cb4 Release preview UI leases even without texture destroy callbacks 2026-10-29 13:34:25 +01:00
evgeny b3f5c49c4d Keep stream catalogue labels current and preserve viewer errors 2026-10-29 13:34:25 +01:00
evgeny 6f0bc4307f Document QR task ownership and application license assets 2026-10-29 13:34:25 +01:00
evgeny f7a80d0a3a Exercise QR cleanup during pending tasks and SDK failures 2026-10-29 13:34:25 +01:00
evgeny 36328814e6 Compile real QR scanner ownership in video host tests 2026-10-29 13:34:25 +01:00
evgeny 41208833b6 Model asynchronous ML Kit tasks and scanner failures in host tests 2026-10-29 13:34:25 +01:00
evgeny 68997853b2 Add CameraX boundaries for QR resource lifecycle tests 2026-10-29 13:34:25 +01:00
evgeny 857338a386 Retain QR scanner resources through asynchronous task completion 2026-10-29 13:34:25 +01:00
evgeny dc09332b2e Share immersive window restoration across stream viewers 2026-10-29 13:34:25 +01:00
evgeny efe421b162 Restore viewer window state and handle photo decoding errors 2026-10-29 13:34:25 +01:00
evgeny bd4bd47e00 Recover join dialog after clipboard and connection errors 2026-10-29 13:34:25 +01:00
evgeny 87b7c6f36c Clarify setup and invitation dialog contracts 2026-10-29 13:34:25 +01:00
evgeny a4a4707c4a Describe NAT snapshots and stream buffer indicator limits 2026-10-29 13:34:25 +01:00
evgeny a442cea1b2 Handle emoji playback failures and clarify image gesture contracts 2026-10-29 13:34:25 +01:00
evgeny 104d70d465 Handle audio device menu launch errors and document UI ownership 2026-10-29 13:34:25 +01:00
evgeny 257df6c520 Describe publisher navigation and video viewport geometry 2026-10-29 13:34:25 +01:00
evgeny 83ba4a03a6 Clarify call banner and status icon presentation contracts 2026-10-29 13:34:25 +01:00
evgeny a7b3d0fc51 Document Telecom cleanup and confirmed route ownership 2026-10-29 13:34:25 +01:00
evgeny eaed746934 Verify radio restoration waits for both service and Telecom release 2026-10-29 13:34:25 +01:00
evgeny e81138e3d1 Await Telecom cleanup before restoring the previous radio session 2026-10-29 13:34:25 +01:00
evgeny 870f1b5914 Clarify Android build modules and handle rejected boot service requests 2026-10-29 13:34:25 +01:00
evgeny 1954c36367 Clarify Telecom ownership and distinguish requested from confirmed cleanup 2026-10-29 13:34:25 +01:00
evgeny 37c72cc2fb Report the retained service ID after the combined teardown check 2026-10-29 13:34:25 +01:00
evgeny 9f1b09aefe Verify Telecom cleanup blocks media and new foreground ownership 2026-10-29 13:34:25 +01:00
evgeny b71f992a45 Retain the media teardown barrier while Telecom cleanup is pending 2026-10-29 13:34:25 +01:00
evgeny e7a03f33fb Cover endpoint callback order and malformed Telecom service requests 2026-10-29 13:34:25 +01:00
evgeny 90e33f568b Validate Telecom request identity and contain extras decoding errors 2026-10-29 13:34:25 +01:00
evgeny 482e1658b0 Preserve the latest route choice while endpoint confirmation is pending 2026-10-29 13:34:25 +01:00
evgeny 8d3cee4a56 Exercise real Telecom ownership, callbacks and endpoint routing 2026-10-29 13:34:25 +01:00
evgeny 8a9e421ea7 Ignore ended Telecom callbacks and contain route listener failures 2026-10-29 13:34:25 +01:00
evgeny f031e510b8 Model Telecom state, endpoint outcomes and ConnectionService requests 2026-10-29 13:34:25 +01:00
evgeny 3babc636b4 Compile real Telecom integration against explicit host boundaries 2026-10-29 13:34:25 +01:00
evgeny 06058fad8e Add URI and main executor boundaries for Telecom host tests 2026-10-29 13:34:25 +01:00
evgeny 7d4a0e05fd Allow explicit Telecom cleanup retry after a rejected timer 2026-10-29 13:34:25 +01:00
evgeny 01a84c6851 Retain retiring Telecom connections and reject duplicate registrations 2026-10-29 13:34:25 +01:00
evgeny c136ff60c2 Document acknowledged publisher shutdown and lifecycle fault coverage 2026-10-29 13:34:25 +01:00
evgeny e5d3a1d584 Cover partial capture startup and callbacks from retired camera owners 2026-10-29 13:34:25 +01:00
evgeny 4af2402e20 Exercise capture ownership across Camera2, Surface, microphone and Opus failures 2026-10-29 13:34:25 +01:00
evgeny 6194538963 Preserve the earliest publisher cleanup retry across repeated shutdowns 2026-10-29 13:34:25 +01:00
evgeny 41a4a2e37e Compile real publisher capture with controlled microphone and native boundaries 2026-10-29 13:34:25 +01:00
evgeny 7a2fc0112c Model capture codec callbacks and Camera2 sessions for host fault tests 2026-10-29 13:34:24 +01:00
evgeny 59d1839d8d Exercise publisher lifecycle failures, retained capture and stale notifications 2026-10-29 13:34:24 +01:00
evgeny f1ffd21cda Report missing publisher system services and use current app language 2026-10-29 13:34:24 +01:00
evgeny 9166268102 Compile publisher service and controller in the lifecycle test harness 2026-10-29 13:34:24 +01:00
evgeny 1beb19a7f8 Expose publisher service boundaries to the existing lifecycle harness 2026-10-29 13:34:24 +01:00
evgeny e49ccfeb64 Guard publisher handshake, error callbacks and native teardown 2026-10-29 13:34:24 +01:00
evgeny 2abdb229fd Keep publisher service owners until capture and foreground cleanup are acknowledged 2026-10-29 13:34:24 +01:00
evgeny 68d21fbffa Acknowledge stream capture shutdown only after every owner is released 2026-10-29 13:34:24 +01:00
evgeny 5e9f7e01e0 Preserve capture camera and session ownership through late callbacks 2026-10-29 13:34:24 +01:00
evgeny fd1e3a7f77 Adopt passive stream capture ownership before starting SDK resources 2026-10-29 13:34:24 +01:00
evgeny 100d208a9a Document stream resource barriers and retained routing registrations 2026-10-29 13:34:24 +01:00
evgeny a1c624a819 Preserve the next KEY after a GAP within one native stream batch 2026-10-29 13:34:24 +01:00
evgeny 0330f30c53 Verify orphan routing listener cleanup and independent route release 2026-10-29 13:34:24 +01:00
evgeny 2516545f9d Retain failed media routing listener removals for acknowledged retry 2026-10-29 13:34:24 +01:00
evgeny ee20c8b9b7 Guard viewer startup and cover the native teardown barrier 2026-10-29 13:34:24 +01:00
evgeny 495d399691 Block native teardown until viewer and shared mixer cleanup is confirmed 2026-10-29 13:34:24 +01:00
evgeny 16c7d817cc Keep mixer shutdown inside the guarded cleanup path 2026-10-29 13:34:24 +01:00
evgeny 304b48a289 Verify stream viewer cleanup barriers with native and SDK faults 2026-10-29 13:34:24 +01:00
evgeny e072624c8d Keep the host audio threshold API compatible with Android signatures 2026-10-29 13:34:24 +01:00
evgeny 68651795bf Compile real stream viewer and mixer for host lifecycle tests 2026-10-29 13:34:24 +01:00
evgeny 5dffa9917f Add controlled native stream and Android audio test boundaries 2026-10-29 13:34:24 +01:00
evgeny 43a749d8ab Use retained Surface leases for stream viewer texture cleanup 2026-10-29 13:34:24 +01:00
evgeny 35fe0ecda1 Exercise stream decoder and audio device failure ownership 2026-10-29 13:34:24 +01:00
evgeny 5b80d5769d Compile the real stream video worker against controlled SDK boundaries 2026-10-29 13:34:24 +01:00
evgeny 26348b35e8 Retain stream audio owners through partial startup and failed release 2026-10-29 13:34:24 +01:00
evgeny f28f95a501 Keep viewer resources and Surface callbacks until cleanup succeeds 2026-10-29 13:34:24 +01:00
evgeny 2f353bf35e Retain stream decoder ownership until worker and SDK cleanup finish 2026-10-29 13:34:24 +01:00
evgeny aa27892c12 Reject regressed stream PTS before submitting it to the decoder 2026-10-29 13:34:24 +01:00
evgeny 5e6313377b Publish verified encoder modes only after successful probe cleanup 2026-10-29 13:34:24 +01:00
evgeny 96f8e6db5b Document acknowledged video shutdown and passive resource adoption 2026-10-29 13:34:24 +01:00
evgeny e9fa7ebb45 Exercise camera teardown despite RX or captured-image cleanup errors 2026-10-29 13:34:24 +01:00
evgeny ea121ac4e7 Model failed-session acknowledgement and verify live preview fallback 2026-10-29 13:34:24 +01:00
evgeny 2068774d58 Clean camera resources independently of RX and image release failures 2026-10-29 13:34:24 +01:00
evgeny e6e3006128 Test Camera2 configuration failure and preview output retention 2026-10-29 13:34:24 +01:00
evgeny 4d559dc08b Handle failed Camera2 sessions without waiting for an absent callback 2026-10-29 13:34:24 +01:00
evgeny 53340db0e3 Verify independent image and codec cleanup under SDK failures 2026-10-29 13:34:24 +01:00
evgeny 43992bb6b3 Expose codec resource ownership to host fault tests 2026-10-29 13:34:24 +01:00
evgeny d9959e5176 Keep codec cleanup diagnostics independent of released SDK handles 2026-10-29 13:34:24 +01:00
evgeny b519536237 Retain codec and input image owners across failed cleanup 2026-10-29 13:34:24 +01:00
evgeny bf3d4f14e8 Keep pending video cleanup distinct from service shutdown failure 2026-10-29 13:34:24 +01:00
evgeny 87e90b9462 Cover late camera callbacks, rejected cleanup and video port recovery 2026-10-29 13:34:24 +01:00
evgeny 776cec590e Retry each pending encoder once per cleanup pass with the shared backoff 2026-10-29 13:34:24 +01:00
evgeny 682ed68d2f Exercise explicit video startup after host tests adopt resource ownership 2026-10-29 13:34:24 +01:00
evgeny 2320aa4f71 Retain the video engine in the call service before starting its workers 2026-10-29 13:34:24 +01:00
evgeny fba07e893f Separate passive video ownership from explicit worker startup 2026-10-29 13:34:24 +01:00
evgeny 5e9dad2e9e Handle camera error callbacks promised alongside synchronous open failures 2026-10-29 13:34:24 +01:00
evgeny a6f41c0256 Confirm camera codec and native video cleanup before acknowledging shutdown 2026-10-29 13:34:24 +01:00
evgeny 53383ec754 Reproduce premature video shutdown acknowledgments and lost camera cleanup owners 2026-10-29 13:34:24 +01:00
evgeny 43f61f6f0b Model pending video shutdown separately from an exception in service tests 2026-10-29 13:34:24 +01:00
evgeny 1ddd2a4a0b Let call service retain video ownership while asynchronous shutdown is pending 2026-10-29 13:34:24 +01:00
evgeny 12db99531f Compile the real call video engine alongside its receive worker in host tests 2026-10-29 13:34:24 +01:00
evgeny 63f393c615 Provide video engine capability, encoder and native port test boundaries 2026-10-29 13:34:24 +01:00
evgeny 3a4e1c6a7c Model Camera2 device session and image reader ownership for lifecycle faults 2026-10-29 13:34:24 +01:00
evgeny 5ad36ba57b Support direct preview buffer sizing and YUV capture format in host fixtures 2026-10-29 13:34:24 +01:00
evgeny 92a301ae54 Provide camera context and fault-controlled orientation sensor boundaries 2026-10-29 13:34:24 +01:00
evgeny 278efd574e Run camera handler tasks on real host worker threads with controlled main timers 2026-10-29 13:34:24 +01:00
evgeny d88d77c14d Specify call snapshot units and the limited config getter interface 2026-10-29 13:34:24 +01:00
evgeny 1596088ca0 Describe camera capability candidates and canonical UDP logger targets 2026-10-29 13:34:24 +01:00
evgeny 8e4d28c1fc Document camera preset restoration, orientation and manual bitrate bounds 2026-10-29 13:34:24 +01:00
evgeny 97f1eaa048 Clarify stream grid and PCM timeline contracts without per-record allocations 2026-10-29 13:34:24 +01:00
evgeny ffa5dece4f Validate stream snapshot counts and verify native metadata mappings 2026-10-29 13:34:24 +01:00
evgeny a1dcf28bf9 Reject malformed stream batches before mutating the playback queue 2026-10-29 13:34:24 +01:00
evgeny 5fb6e72c43 Describe stream source snapshots, codec framing and playback telemetry contracts 2026-10-29 13:34:24 +01:00
evgeny cc7648bb33 Validate length-prefixed NAL headers consistently with Annex B input 2026-10-29 13:34:24 +01:00
evgeny 92ce2d84e9 Describe preview lease transfer, callback cancellation and physical cleanup retries 2026-10-29 13:34:24 +01:00
evgeny 0a777baabb Adopt a fresh preview lease when a previous command lease was cancelled 2026-10-29 13:34:24 +01:00
evgeny 44a137e23b Verify preview ownership, callback rollback and independent physical release retries 2026-10-29 13:34:24 +01:00
evgeny 4d15c6d42a Keep preview cleanup retryable after scheduling rejection and compile real leases in host tests 2026-10-29 13:34:24 +01:00
evgeny 83ea839d0c Recognize shared preview sources and model texture cleanup failures 2026-10-29 13:34:24 +01:00
evgeny 4a40fb9d52 Give preview owners independent leases and retain failed physical cleanup 2026-10-29 13:34:24 +01:00
evgeny 4ba21b3082 Remove the trailing blank line from the audited video JNI declarations 2026-10-29 13:34:24 +01:00
evgeny b2b34df2ec Document video receive cleanup acknowledgments and host fault coverage 2026-10-29 13:34:24 +01:00
evgeny 8040431a4a Specify call video bitrate, cadence and orientation helper contracts 2026-10-29 13:34:24 +01:00
evgeny 98cd5bf81c Describe call video JNI buffers, return values and playout handle ownership 2026-10-29 13:34:24 +01:00
evgeny 000273d451 Keep the earliest pending video cleanup retry instead of postponing it twice 2026-10-29 13:34:24 +01:00
evgeny d8fd73d917 Exercise video RX cleanup failures, surface leases and generation draining 2026-10-29 13:34:24 +01:00
evgeny 71e1e5c747 Run real call video receive tests with controlled native and codec boundaries 2026-10-29 13:34:24 +01:00
evgeny 7f89b7c734 Provide controlled MediaCodec input output and cleanup failures 2026-10-29 13:34:24 +01:00
evgeny 8951af6b63 Model video surfaces and deterministic cleanup retry timers on the JVM 2026-10-29 13:34:24 +01:00
evgeny af2209ec96 Prepare host video tests and initialize receive ownership before starting its worker 2026-10-29 13:34:24 +01:00
evgeny eff6f8965a Retain video receive resources through failed decoder and surface cleanup 2026-10-29 13:34:24 +01:00
evgeny 448fa39a0c Separate call video format values from the native runtime boundary 2026-10-29 13:34:24 +01:00
evgeny 99ab91d2f5 Clarify router cleanup as a native audio teardown prerequisite 2026-10-29 13:34:24 +01:00
evgeny bc6ca78ce8 Document retained router resources and shared session close acknowledgments 2026-10-29 13:34:23 +01:00
evgeny 774dc10d84 Preserve configured Telecom ownership when startup retries router cleanup 2026-10-29 13:34:23 +01:00
evgeny e660f8f762 Cover partial communication selection and SCO cleanup effects 2026-10-29 13:34:23 +01:00
evgeny 8cdb4190b6 Log rejected media operations while session cleanup remains pending 2026-10-29 13:34:23 +01:00
evgeny a6f8156564 Track possible SCO effects before starting the Android request 2026-10-29 13:34:23 +01:00
evgeny 48ab63a9d3 Test router cleanup barriers in call and shared media owners 2026-10-29 13:34:23 +01:00
evgeny b3e1356d16 Exercise retained router cleanup, stale proxies and SCO failure recovery 2026-10-29 13:34:23 +01:00
evgeny 3ef245fc0a Verify pending router cleanup through repeatable stop calls 2026-10-29 13:34:23 +01:00
evgeny f7ebf81061 Ignore repeated Bluetooth callbacks for proxies already released 2026-10-29 13:34:23 +01:00
evgeny 3d2e98b02e Keep media audio session close retryable until router cleanup succeeds 2026-10-29 13:34:23 +01:00
evgeny 1970f895da Retain router resources and retry incomplete audio route cleanup 2026-10-29 13:34:23 +01:00
evgeny 1da06164e2 Document retryable call audio shutdown and device ownership 2026-10-29 13:34:23 +01:00
evgeny 94b5d44fe7 Check call audio main ownership and the late Telecom handoff 2026-10-29 13:34:23 +01:00
evgeny 326bfd124e Guard call audio ownership on main and avoid touching released devices 2026-10-29 13:34:23 +01:00
evgeny 0340a59b15 Dispatch host mainExecutor callbacks through the main looper 2026-10-29 13:34:23 +01:00
evgeny f385d3dc5e Cover call audio teardown and partial device startup failures 2026-10-29 13:34:23 +01:00
evgeny 83a671b72f Compile the real call audio engine in host regression tests 2026-10-29 13:34:23 +01:00
evgeny ecd4e12274 Provide call DSP and Telecom boundaries for real audio worker tests 2026-10-29 13:34:23 +01:00
evgeny 7304647baa Model call audio hardware failures and blocking capture on the JVM 2026-10-29 13:34:23 +01:00
evgeny e857b9de75 Retain call audio owners until worker and device cleanup succeeds 2026-10-29 13:34:23 +01:00
evgeny a1c77268b8 Document retained call service cleanup, retry policy and native core teardown barriers 2026-10-29 13:34:23 +01:00
evgeny 6ac6dd1f6f Describe call teardown acknowledgments and the boundary of asynchronous video cleanup 2026-10-29 13:34:23 +01:00
evgeny 02763bd4a1 Reject missing service components instead of waiting forever for Android startup 2026-10-29 13:34:23 +01:00
evgeny 4dd84c601b Cover null foreground service results in call and overlay startup 2026-10-29 13:34:23 +01:00
evgeny d2c6734bfb Model Android service requests that return no matching component 2026-10-29 13:34:23 +01:00
evgeny 17dc0b26b4 Preserve the service call identity until its final lifecycle notification 2026-10-29 13:34:23 +01:00
evgeny 42c6e2a62b Keep service loss associated with the call after local resources are released 2026-10-29 13:34:23 +01:00
evgeny 9b0ca7ca2b Document call service resource acknowledgments and contain conflict callback errors 2026-10-29 13:34:23 +01:00
evgeny aefca81444 Keep cancelled media preparation inside the native teardown barrier 2026-10-29 13:34:23 +01:00
evgeny ca7b23909b Use retained resource ownership instead of Deferred cancellation as the cleanup barrier 2026-10-29 13:34:23 +01:00
evgeny a5d8131d8d Verify call cleanup completion, core barriers, retry lifetime and stale callbacks 2026-10-29 13:34:23 +01:00
evgeny 3e7ac47d18 Close the independent call service cleanup block at the correct scope 2026-10-29 13:34:23 +01:00
evgeny 826055d08b Keep failed video shutdown joins and rejected cleanup requests retryable 2026-10-29 13:34:23 +01:00
evgeny 878f71e211 Wait for call service cleanup before restoring media and stopping the native core 2026-10-29 13:34:23 +01:00
evgeny cf793ce6bb Confirm call cleanup before releasing ownership and retry every retained resource independently 2026-10-29 13:34:23 +01:00
evgeny 8eb2363177 Retain call service startup owners before IPC effects and isolate callback failures 2026-10-29 13:34:23 +01:00
evgeny 4f9bfbbcf3 Reference the host service lifecycle result through its Android boundary 2026-10-29 13:34:23 +01:00
evgeny ff05e34d22 Compile call integration models and contain missing notification service errors 2026-10-29 13:34:23 +01:00
evgeny 9c70858828 Exercise call service startup, partial IPC effects and independent cleanup failures 2026-10-29 13:34:23 +01:00
evgeny dd9aac79a2 Handle absent notification managers and nullable call channels explicitly 2026-10-29 13:34:23 +01:00
evgeny 15a2a7bb70 Control audio and video cleanup effects around the real call service controller 2026-10-29 13:34:23 +01:00
evgeny be3a2d2325 Add isolated host checks for the real call service and controller 2026-10-29 13:34:23 +01:00
evgeny bc7063966d Expose call signaling and saved route boundaries to service integration tests 2026-10-29 13:34:23 +01:00
evgeny 1600452147 Model call power events and supported foreground API levels 2026-10-29 13:34:23 +01:00
evgeny 68b922bf80 Expose call foreground intents, receivers and service type contracts 2026-10-29 13:34:23 +01:00
evgeny 0a48cccd9a Model ongoing call notifications and independent foreground stop failures 2026-10-29 13:34:23 +01:00
evgeny a65385bbb1 Keep radio outcomes separate from the live stream foreground notification 2026-10-29 13:34:23 +01:00
evgeny a90416f50c Preserve stream notifications and synchronize host checks with audio cleanup 2026-10-29 13:34:23 +01:00
evgeny 0d9dabcd23 Cover touch permission checks with the overlay error boundary 2026-10-29 13:34:23 +01:00
evgeny 4de7d7ec9d Document overlay service handshake, window cleanup and gesture error ownership 2026-10-29 13:34:23 +01:00
evgeny 1559e0681b Verify overlay latch release, drag lock and position ownership contracts 2026-10-29 13:34:23 +01:00
evgeny 5553d968b6 Deliver cancelled service creation and account for self-context stop requests 2026-10-29 13:34:23 +01:00
evgeny abef146325 Stop unused overlay foreground capture after touch and permission failures 2026-10-29 13:34:23 +01:00
evgeny 36368640f1 Exercise overlay PTT through native capture and permission-loss stop races 2026-10-29 13:34:23 +01:00
evgeny 982315bacc Cancel overlay PTT on gesture faults and ignore callbacks from retired windows 2026-10-29 13:34:23 +01:00
evgeny b3d70ea92e Retain overlay windows through partial IPC failures and guarded service startup 2026-10-29 13:34:23 +01:00
evgeny fa14305349 Avoid a host settings getter collision with the application API 2026-10-29 13:34:23 +01:00
evgeny 08f3b892a5 Separate overlay notification ownership and recover rejected service actions 2026-10-29 13:34:23 +01:00
evgeny d6c178a39b Keep host window lookup separate from the service-owned window field 2026-10-29 13:34:23 +01:00
evgeny 18cb661c91 Reproduce overlay partial IPC effects, stale gestures and foreground lifecycle failures 2026-10-29 13:34:23 +01:00
evgeny 2f43407ae4 Require an available notification manager at overlay IPC boundaries 2026-10-29 13:34:23 +01:00
evgeny 19050cd4f2 Use the real overlay service with radio lifecycle components in host tests 2026-10-29 13:34:23 +01:00
evgeny ff16eec78d Expose overlay notification and state resource identifiers to JVM tests 2026-10-29 13:34:23 +01:00
evgeny 263d1348ec Model overlay permissions and persistent settings for service tests 2026-10-29 13:34:23 +01:00
evgeny ce756ed6a9 Expose foreground type and deferred layout contracts in overlay fixtures 2026-10-29 13:34:23 +01:00
evgeny 19fd2d3042 Provide overlay drawing boundaries without Android rendering 2026-10-29 13:34:23 +01:00
evgeny d1dc3bb8f7 Model overlay window IPC and foreground service lifetime for Android host tests 2026-10-29 13:34:23 +01:00
evgeny 6d5b2bd176 Record distinct radio core availability and busy outcomes 2026-10-29 13:34:23 +01:00
evgeny 6ee4aa99eb Report unavailable core accurately and include malformed radio event fields 2026-10-29 13:34:23 +01:00
evgeny 16a9bee8f3 Distinguish unavailable radio signaling from an occupied call slot 2026-10-29 13:34:23 +01:00
evgeny 8100ea728e Document Android radio invitation ownership, UI phases and fault checks 2026-10-29 13:34:23 +01:00
evgeny 6ec8950a85 Clarify asynchronous radio signaling and wire identity contracts 2026-10-29 13:34:23 +01:00
evgeny cda411a57e Document radio invitation state and cover continuation and stale pending events 2026-10-29 13:34:23 +01:00
evgeny 45992a3dd3 Allow the missing-notification-service fault in radio cleanup assertions 2026-10-29 13:34:23 +01:00
evgeny 8a7f732428 Validate radio call identities and preserve terminal activation states 2026-10-29 13:34:23 +01:00
evgeny b24bee7a89 Own pending radio starts and diagnose every signaling queue refusal 2026-10-29 13:34:23 +01:00
evgeny 16f52c0136 Exercise radio call signaling refusals, identity, activation and notification lifetime 2026-10-29 13:34:23 +01:00
evgeny 93b174ecde Keep radio outcome presentation failures inside the controller lifecycle 2026-10-29 13:34:23 +01:00
evgeny 8b982efa05 Compile the real radio call controller in host lifecycle tests 2026-10-29 13:34:23 +01:00
evgeny a5718c4ca9 Model native radio call requests and controller dependencies in host fixtures 2026-10-29 13:34:23 +01:00
evgeny 5823d6f907 Bind capture startup to the generation of its update request 2026-10-29 13:34:23 +01:00
evgeny 7810137eb0 Handle playback cancellation and document complete radio failure recovery 2026-10-29 13:34:23 +01:00
evgeny b1a888ffb6 Distinguish stop-unblocked writes from active playback failures 2026-10-29 13:34:23 +01:00
evgeny a5fea0c503 Preserve replacement PTT requests during obsolete capture rollback 2026-10-29 13:34:23 +01:00
evgeny 17caeb0a9c Cover capture startup failures that overlap a replacement group 2026-10-29 13:34:23 +01:00
evgeny 6677b3abfe Document radio worker ownership and format failure boundaries 2026-10-29 13:34:23 +01:00
evgeny 613ea315b0 Synchronize radio discontinuity regression with the first capture frame 2026-10-29 13:34:23 +01:00
evgeny ed8d208454 Recover radio worker failures on the owning I/O executor 2026-10-29 13:34:23 +01:00
evgeny a04cfe4441 Keep radio capture owned through startup faults and deferred native cleanup 2026-10-29 13:34:23 +01:00
evgeny 1ddd75e134 Isolate complete short-write frames from playback already in flight 2026-10-29 13:34:23 +01:00
evgeny 9baa72759f Reproduce radio worker failures and stale session cleanup races 2026-10-29 13:34:23 +01:00
evgeny 5d74bcd865 Model radio worker I/O faults and partial native capture effects 2026-10-29 13:34:23 +01:00
evgeny 128af68a89 Invalidate radio settings before reconfiguration and log failed attempts 2026-10-29 13:34:23 +01:00
evgeny 67615cc330 Reproduce stale settings acknowledgements after failed radio reconfiguration 2026-10-29 13:34:23 +01:00
evgeny bb8518ab67 Document radio startup completion and independent cleanup contracts 2026-10-29 13:34:23 +01:00
evgeny 2fd8a35230 Verify failed radio restore and trace resource join completion 2026-10-29 13:34:23 +01:00
evgeny b6ec030128 Bind radio screen callbacks to the originating startup generation 2026-10-29 13:34:23 +01:00
evgeny 7084454e84 Verify radio output lease dependencies and interrupted cleanup 2026-10-29 13:34:23 +01:00
evgeny 7699ebfcf6 Own radio acknowledgement timers and close unschedulable background capture 2026-10-29 13:34:23 +01:00
evgeny 0ba189863e Complete radio startup callbacks after failures and reject stale readiness 2026-10-29 13:34:23 +01:00
evgeny e197f72722 Release radio resources independently and retain failed cleanup owners 2026-10-29 13:34:23 +01:00
evgeny 530dd81a71 Isolate old radio cleanup failures between negative control scenarios 2026-10-29 13:34:23 +01:00
evgeny c1fe2a3cd0 Reproduce radio lifecycle cleanup and startup callback failures 2026-10-29 13:34:23 +01:00
evgeny 45bc97c25b Model radio startup and main queue delivery failures 2026-10-29 13:34:23 +01:00
evgeny 982ed0ca7d Model recoverable receiver and radio output lifecycle failures 2026-10-29 13:34:23 +01:00
evgeny 7780922353 Document radio PTT release fallback and native command coverage 2026-10-29 13:34:22 +01:00
evgeny 46edb1beb5 End radio PTT immediately when its release timer is rejected 2026-10-29 13:34:22 +01:00
evgeny 722ca3e6f7 Drain radio callbacks before terminating the host executor 2026-10-29 13:34:22 +01:00
evgeny ef95ff54b9 Reproduce stuck radio PTT and verify native release ordering 2026-10-29 13:34:22 +01:00
evgeny a162cc6eca Compile the real radio engine in Android host tests 2026-10-29 13:34:22 +01:00
evgeny f494c20430 Keep radio overlay and toast boundaries outside host audio logic 2026-10-29 13:34:22 +01:00
evgeny 6df258cf13 Provide microphone permission resources for radio host tests 2026-10-29 13:34:22 +01:00
evgeny 81b9469302 Observe native radio capture and PTT commands in host tests 2026-10-29 13:34:22 +01:00
evgeny 4ff2f56aa8 Provide radio screen state and monotonic nanoseconds to host tests 2026-10-29 13:34:22 +01:00
evgeny 841d4ecdde Model radio screen receiver registration in host tests 2026-10-29 13:34:22 +01:00
evgeny 51611cbf5a Model radio playback without Android audio hardware 2026-10-29 13:34:22 +01:00
evgeny 9d6018cdbb Describe radio manual holds and independent speaker indication 2026-10-29 13:34:22 +01:00
evgeny 95894273f1 Document radio PTT ownership and talk event state contracts 2026-10-29 13:34:22 +01:00
evgeny 43b14ece78 Unify UDP and STCP packet link API with bounded backpressure 2026-10-29 12:53:57 +01:00
evgeny 3203947698 Add desktop log rotation on startup and size limit 2026-10-29 11:23:36 +01:00
evgeny ba1c4cf160 Add cross-platform BLE transport and Bluetooth settings
Integrate shared C transport with desktop and Android frontends, add radio probes and detailed Windows diagnostics, and fix GUI build dependencies and early configuration startup errors.
2026-10-29 10:51:19 +01:00
evgeny 221f58c9d2 Draw storage avatars as clear cylinders with curved bands 2026-10-28 17:58:40 +01:00
evgeny 54fdd167c2 Use server and storage role icons instead of member avatars 2026-10-28 17:49:24 +01:00
evgeny c96a63091c Replace supernode lightning with a server icon renderer 2026-10-28 17:48:54 +01:00
evgeny 2b05140e74 Verify actual route labels and local to peer NAT pairs in member details 2026-10-28 17:21:37 +01:00
evgeny faa75a7e1d Show actual member routes and both endpoints' NAT types in desktop details 2026-10-28 17:20:46 +01:00
evgeny 26edd84bb9 Enable MJPEG thumbnail encoding and refresh bundled FFmpeg during Windows builds 2026-10-28 15:56:18 +01:00
evgeny 19cece789e Remove local test databases from version control and ignore their directories 2026-10-28 15:38:52 +01:00
evgeny 9cabb698e2 Exercise cached media preparation in real history widgets across scrolling and reopening 2026-10-28 15:09:35 +01:00
evgeny ba44c31f42 Add focused cache and prepared media rendering checks to desktop tests 2026-10-28 15:06:43 +01:00
evgeny ed19adc1ba Cover persistent preview reuse, PNG alpha, first video frame, rotation and creation based expiry 2026-10-28 15:06:06 +01:00
evgeny 806632b67d Link the persistent preview cache and keep image preparation free of temporary files 2026-10-28 15:04:03 +01:00
evgeny 73b1fc7080 Render cached image and video previews without filesystem access or scaled pixmap allocation 2026-10-28 15:02:28 +01:00
evgeny 60d2ba0fac Prepare visible image and video previews through the shared background cache 2026-10-28 15:01:29 +01:00
evgeny 468af7abbe Add persistent media preview cache with fixed creation timestamps and seven day expiry 2026-10-28 14:57:54 +01:00
evgeny fc5ad51ec3 Clarify ringing phase precedes accepting the call 2026-10-28 14:43:27 +01:00
evgeny 6a82192b02 Document ringback and notification playback ownership contracts 2026-10-28 14:43:27 +01:00
evgeny 776345997f Keep notification players strongly owned throughout playback 2026-10-28 14:43:27 +01:00
evgeny b318627022 Require confirmed media release in existing alert lifecycle tests 2026-10-28 14:43:27 +01:00
evgeny 0b10a38f41 Retain failed media releases and retry without replacing ringback owners 2026-10-28 14:43:27 +01:00
evgeny 383da15d95 Allow absent callbacks after partial ringback listener setup 2026-10-28 14:43:27 +01:00
evgeny 2a4ccd8ca8 Reproduce lost ringback and notification players after release failures 2026-10-28 14:43:27 +01:00
evgeny 512a87502b Document ringtone resource ownership and cleanup retry contracts 2026-10-28 14:43:27 +01:00
evgeny 27b99435c0 Clarify alert stop diagnostics when sound cleanup remains pending 2026-10-28 14:43:27 +01:00
evgeny e45ddd2a7f Require confirmed cleanup in existing ringtone lifecycle tests 2026-10-28 14:43:27 +01:00
evgeny 94b9786d91 Retain ringtone resources and retry cleanup before replacement 2026-10-28 14:43:27 +01:00
evgeny 6abedd8177 Reproduce lost ringtone and focus owners after cleanup failures 2026-10-28 14:43:27 +01:00
evgeny cc9e4f4d85 Model rejected vibration scheduling and partial cancellation 2026-10-28 14:43:27 +01:00
evgeny 7ed1a63b36 Model recoverable alert playback and focus cleanup failures 2026-10-28 14:43:27 +01:00
evgeny edc6b32fa7 Cover orphan notification cleanup through language refresh 2026-10-28 14:43:27 +01:00
evgeny d67991d08a Avoid repeated alert cancellation after successful lifecycle cleanup 2026-10-28 14:43:27 +01:00
evgeny 61e013e762 Check lifecycle refresh does not repeat completed alert cleanup 2026-10-28 14:43:27 +01:00
evgeny 774284b699 Verify repeated cleanup across incoming alert lifecycle failures 2026-10-28 14:43:27 +01:00
evgeny 66e99066f9 Retain incoming alert resources until cleanup succeeds 2026-10-28 14:43:27 +01:00
evgeny 793c2b251b Reproduce lost incoming alert resources after cleanup exceptions 2026-10-28 14:43:27 +01:00
evgeny f4cfe5ba30 Model partial wake lock and notification cleanup failures 2026-10-28 14:43:27 +01:00
evgeny 3a6ef25ca6 Document requested locales and notification language refresh contracts 2026-10-28 14:43:27 +01:00
evgeny 7b8e0a95bb Document language host tests and their runtime boundaries 2026-10-28 14:43:27 +01:00
evgeny 3dfedc8822 Read back locale requests after partial framework failures 2026-10-28 14:43:27 +01:00
evgeny a541484df1 Expose language read and selection failures in the settings UI 2026-10-28 14:43:27 +01:00
evgeny caccb4e56f Add localized language selection and catalog error messages 2026-10-28 14:43:27 +01:00
evgeny 8537ac1e6d Include language lifecycle coverage in Android unit test runs 2026-10-28 14:43:27 +01:00
evgeny 4bffffb0ad Keep language tests compatible with an expanded XML catalog 2026-10-28 14:43:27 +01:00
evgeny 6133257c24 Validate language catalogs and framework failure contracts on the host 2026-10-28 14:43:27 +01:00
evgeny 8720cee7af Keep the headless service fixture separate from Android sources 2026-10-28 14:43:27 +01:00
evgeny fd183a43fe Retry notification language refreshes on every configuration signal 2026-10-28 14:43:27 +01:00
evgeny 5360ee9ff1 Reproduce skipped notification language retries and callback failures 2026-10-28 14:43:27 +01:00
evgeny 9369429600 Observe independent notification refresh attempts in language tests 2026-10-28 14:43:27 +01:00
evgeny 909761b0c5 Provide application and main thread boundaries for language tests 2026-10-28 14:43:27 +01:00
evgeny 638a2a2d6b Model locale resources and AppCompat failures for language tests 2026-10-28 14:43:27 +01:00
evgeny aae145b82a Prepare isolated host tests for application language behavior 2026-10-28 14:43:27 +01:00
evgeny 5e0ed8b077 Document battery exemption query and settings request contracts 2026-10-28 14:43:27 +01:00
evgeny 8551234cfb Show unknown battery exemption state with an explicit retry action 2026-10-28 14:43:27 +01:00
evgeny 0b31f27177 Preserve unknown battery exemption status on Android service errors 2026-10-28 14:43:27 +01:00
evgeny 04b76be1c8 Compile the battery permission adapter in Android host tests 2026-10-28 14:43:27 +01:00
evgeny ff08f05e9a Model power exemption queries and system activity launch failures 2026-10-28 14:43:27 +01:00
evgeny 4b221ef0d1 Verify growing call preview and emphasized metric values 2026-10-28 14:35:46 +01:00
evgeny 859f33b5e9 Expand call preview to the available window area and emphasize diagnostic values 2026-10-28 14:34:12 +01:00
evgeny b03d101c87 Check call diagnostics, avatar visibility and bottom action alignment 2026-10-28 14:20:36 +01:00
evgeny 309754244a Localize call diagnostics and keep video parameters in logs 2026-10-28 14:20:36 +01:00
evgeny b82e9cc98e Pin call actions to the bottom and add a separate diagnostics toggle 2026-10-28 14:19:14 +01:00
evgeny 264a13705f Finalize shared frame rate selection and deterministic call control verification 2026-10-28 14:10:53 +01:00
evgeny bb0fa13c8b Show audio output captions and validate the desktop call settings menus 2026-10-28 14:08:21 +01:00
evgeny 2540909fda Replace desktop call settings with compact capture control menus 2026-10-28 14:06:40 +01:00
evgeny f76aacfba1 Share resolution dependent frame rate menus for capture settings 2026-10-28 14:04:31 +01:00
evgeny f9c150b7d4 Share capture control menus and Android style glyphs between desktop windows 2026-10-28 14:02:39 +01:00
evgeny 7be5c8bd0b Verify rendered control sizes and muted stream startup 2026-10-28 13:57:05 +01:00
evgeny 287b54b283 Allow and remember stream audio toggling before publication starts 2026-10-28 13:55:45 +01:00
evgeny c932528217 Apply initial stream mute before opening capture devices 2026-10-28 13:55:15 +01:00
evgeny 26953fc1a4 Render broadcast controls at their actual icon size with Android style values and rotation 2026-10-28 13:55:14 +01:00
evgeny 01dd40fdd1 Double broadcast control icons and tighten button spacing 2026-10-28 13:47:09 +01:00
evgeny 07b8c2b338 Keep broadcast menu style alive through menu teardown and add English labels 2026-10-28 13:44:02 +01:00
evgeny 21ab92d2b4 Update broadcast control tests and Russian menu labels 2026-10-28 13:42:58 +01:00
evgeny 35875a2c43 Move desktop broadcast settings into compact top menus with separate resolution and FPS 2026-10-28 13:41:09 +01:00
evgeny 7d3f0852f7 Place video settings in the centered desktop call control row 2026-10-28 13:25:24 +01:00
evgeny f1da7e1837 Center desktop call actions and use a gear button for video settings 2026-10-28 13:17:19 +01:00
evgeny 75336387c5 Translate desktop video settings and camera toggles 2026-10-28 13:09:42 +01:00
evgeny 858e27ec8c Replace desktop call video checkbox with a round camera button 2026-10-28 13:09:42 +01:00
evgeny 270eb0c3b0 android: add photo and video capture orientation controls 2026-10-28 12:58:21 +01:00
evgeny 19a3cc8934 Merge remote-tracking branch 'origin/master' 2026-10-28 12:43:38 +01:00
evgeny f9ccca85bb Insert generated config fields before blank section separators 2026-10-28 12:41:10 +01:00
evgeny 41930a35c4 Audit configuration sample against current parser and service behavior 2026-10-28 12:36:21 +01:00
evgeny 2c82ceaad7 Handle nullable multicast lock creation before acquiring ownership 2026-10-28 12:28:28 +01:00
evgeny 3c5a9410ec Clarify retained LAN delivery state after core shutdown 2026-10-28 12:28:28 +01:00
evgeny 25dda68ecf Document LAN invitation framing and server link preview contracts 2026-10-28 12:28:28 +01:00
evgeny 237ba93e1a Report invitation presentation errors without exposing link secrets 2026-10-28 12:28:28 +01:00
evgeny 6f9ddc88e2 Add localized invitation copy errors and delivery recipient labels 2026-10-28 12:28:28 +01:00
evgeny f910d235fd Validate LAN events and retain multicast lock ownership on errors 2026-10-28 12:28:28 +01:00
evgeny 0be56a133b Reproduce LAN invitation state and multicast ownership failures 2026-10-28 12:28:28 +01:00
evgeny 0b8caaa810 Model LAN invitation JNI calls and multicast lock failures 2026-10-28 12:28:28 +01:00
evgeny e32e4be28b Document JNI log encoding and failure containment contracts 2026-10-28 12:28:28 +01:00
evgeny c137ad89d1 Clarify JNI log scenario coverage and callback descriptor checks 2026-10-28 12:28:28 +01:00
evgeny 1c705e64ca Verify repeated JNI delivery and log subscription changes 2026-10-28 12:28:28 +01:00
evgeny 269d09815b Document JNI host checks and their platform requirements 2026-10-28 12:28:28 +01:00
evgeny 0931eeedad Run JNI log fault scenarios with Android unit tests 2026-10-28 12:28:28 +01:00
evgeny a77fc553e7 Contain JNI logging failures and preserve UTF-8 payloads 2026-10-28 12:28:28 +01:00
evgeny c656e3a96b Reproduce Android JNI log callback failures on the host 2026-10-28 12:28:28 +01:00
evgeny 8268c5112c Describe Android log retention and diagnostic output contracts 2026-10-28 12:28:28 +01:00
evgeny 401e65c132 Read Android log snapshots without losing queued updates 2026-10-28 12:28:28 +01:00
evgeny 69cb7664f3 Update chatserver sample for generated addition key 2026-10-28 12:26:35 +01:00
evgeny 38d24e7bbf Document opt-in Android network logging 2026-10-28 12:08:07 +01:00
evgeny 0c2b96ee95 Add a logreceiver checkbox to Android debug settings 2026-10-28 12:08:07 +01:00
evgeny 0a36dc5ac6 Make Android UDP log forwarding opt-in with a persisted target 2026-10-28 12:08:07 +01:00
evgeny 917a2a2b28 Serialize stream capture preferences with other saved media profiles 2026-10-28 12:08:07 +01:00
evgeny 7ed8f90068 Keep call controls visible while a video menu is open 2026-10-28 12:08:07 +01:00
evgeny c0acb6b268 Remember separate photo and video recording preferences 2026-10-28 12:08:07 +01:00
evgeny c9f8f17858 Restore video call modes and remember the selected bitrate range 2026-10-28 12:08:07 +01:00
evgeny 76f81bc14e Store independent capture profiles in the application settings queue 2026-10-28 12:08:07 +01:00
evgeny 9f1c1cf9e4 Add titled one-tap menus to stream capture and audio controls 2026-10-28 12:08:07 +01:00
evgeny 211f8f4c5d Keep the video bitrate slider aligned with its saved range 2026-10-28 12:08:07 +01:00
evgeny c368b77a00 Unify video call controls and support one-tap option menus 2026-10-28 12:08:07 +01:00
evgeny ead884e6d3 Prefer the main rear camera in photo mode 2026-10-28 12:08:07 +01:00
evgeny 067a6bd801 Switch camera menus in one tap and toggle the current menu 2026-10-28 12:08:07 +01:00
evgeny 217a4bb27b Add descriptive headers to camera option menus 2026-10-28 12:08:07 +01:00
evgeny 93da173987 Default camera JPEG quality to 85 and remove lowest presets 2026-10-28 12:08:07 +01:00
evgeny a53668ade8 Show captured JPEG file size and enlarge camera metadata text 2026-10-28 12:08:07 +01:00
evgeny 07c9cf223c Hide camera discard and send actions until there is captured media 2026-10-28 12:08:07 +01:00
evgeny f351f289af Center camera actions and replace inactive shutter with a half-width gap 2026-10-28 12:08:07 +01:00
evgeny 22c8f9a69c Place compact photo and video details beside camera controls 2026-10-28 12:08:07 +01:00
evgeny 1359247e3f Describe recording codec checks and JPEG quality preview 2026-10-28 12:08:07 +01:00
evgeny c7b301b3a1 Document updated Android build stack and keep capture diagnostics compact 2026-10-28 12:08:07 +01:00
evgeny 03059e3001 Choose recording codec, resolution and bitrate independently and set JPEG quality 2026-10-28 12:08:07 +01:00
evgeny afa6af5012 Share compact bitrate labels between streaming and recording controls 2026-10-28 12:08:06 +01:00
evgeny aaf0617a1f Upgrade Android build tools and CameraX while retaining API 26 minimum 2026-10-28 12:08:06 +01:00
evgeny b84561dba5 Use shared capture icons and menus for camera and resolution selection 2026-10-28 12:08:06 +01:00
evgeny 379e7731df Align Android camera timer to the right of the control panel 2026-10-28 12:08:06 +01:00
evgeny 4aa5513f25 Keep Android camera settings and controls outside the preview 2026-10-28 12:08:06 +01:00
evgeny 10a4554c81 Localize desktop image validation errors 2026-10-28 12:08:06 +01:00
evgeny c84c328c90 Align camera navigation and developer references with shared capture screen 2026-10-28 12:08:06 +01:00
evgeny 4f5e46e9a9 Keep cache sources alive while accepted legacy image copies are pending 2026-10-28 12:08:06 +01:00
evgeny 2ac483f10f Document image attachment metadata and shared Android camera ownership 2026-10-28 12:08:06 +01:00
evgeny 199eaa0429 Verify desktop image previews decode asynchronously and paint without file I/O 2026-10-28 12:08:06 +01:00
evgeny 154c76068c Check encrypted image dimensions across the Android bridge 2026-10-28 12:08:06 +01:00
evgeny b3e7db7b26 Cover encrypted group images and fixed private generation in desktop submission tests 2026-10-28 12:08:06 +01:00
evgeny 206abcae10 Test typed desktop images in channels and PM and reject corrupted attachments 2026-10-28 12:08:06 +01:00
evgeny 3c74fc89fe Handle camera cache failures and remove unused photo submission wrapper 2026-10-28 12:08:06 +01:00
evgeny 684062c115 Test image metadata, private attachment publication and Android cache ownership 2026-10-28 12:08:06 +01:00
evgeny c6fdf52582 Decode desktop image previews in bounded background jobs 2026-10-28 12:08:06 +01:00
evgeny 08e9b62e16 Render image previews from prepared model data and preserve aspect ratios 2026-10-28 12:08:06 +01:00
evgeny 04d9d1f2b9 Connect shared camera and photo viewer to Android channel and PM navigation 2026-10-28 12:08:06 +01:00
evgeny 6e30fd474e Unify Android photo and video capture with explicit cache ownership 2026-10-28 12:08:06 +01:00
evgeny 8ff6694c5a Show bounded image previews and open zoomable photos in Android private chats 2026-10-28 12:08:06 +01:00
evgeny d1bb143928 Add localized image and camera error states 2026-10-28 12:08:06 +01:00
evgeny 4228f37cf5 Recognize image contents and preserve image dimensions in Android conversations 2026-10-28 12:08:06 +01:00
evgeny 233a3f78d1 Pass image MIME and private conversation generation through Android JNI 2026-10-28 12:08:06 +01:00
evgeny e4af3907c2 Prepare Android JPEG and PNG attachments for fixed channel or PM targets 2026-10-28 12:08:06 +01:00
evgeny 23fecc2c11 Send and display JPEG and PNG in desktop private conversations 2026-10-28 12:08:06 +01:00
evgeny e3b09bd0b7 Support JPEG and PNG attachment metadata and preparation 2026-10-28 12:08:06 +01:00
evgeny 78ea57d183 Clarify conversation rendering and preserve quote Unicode 2026-10-28 11:36:13 +01:00
evgeny 0b285ec19b Move the logs shortcut beside the CPU indicator 2026-10-28 11:36:13 +01:00
evgeny 8b3b6fb5af Reject malformed feedback events before updating UI state 2026-10-28 11:36:13 +01:00
evgeny 317f362a7a Reproduce malformed feedback event handling in the UI 2026-10-28 11:36:13 +01:00
evgeny a1ce486e89 Document feedback snapshots and poll UI submission contracts 2026-10-28 11:36:13 +01:00
evgeny 37515df8c1 Validate poll drafts and reject malformed feedback snapshots 2026-10-28 11:36:13 +01:00
evgeny 89efd10450 Reproduce invalid poll draft and inactive custom answer handling 2026-10-28 11:36:13 +01:00
evgeny f6b5e5b42c Route group avatar snapshots separately from feedback changes 2026-10-28 11:36:13 +01:00
evgeny d969b277e1 Assign a registered event ID to Android group avatar snapshots 2026-10-28 11:36:13 +01:00
evgeny e91987d241 Reproduce Android avatar and feedback event ID collision 2026-10-28 11:36:13 +01:00
evgeny 69bc182ee9 Clarify capture timeline and microphone permission contracts 2026-10-28 11:36:13 +01:00
evgeny c0c282ca3a Make voice recording ownership and playback failures explicit 2026-10-28 11:36:13 +01:00
evgeny 0219624c7d Reproduce voice capture rollback and playback cleanup failures 2026-10-28 11:36:13 +01:00
evgeny 537814e7fd Model microphone permission for voice recorder host tests 2026-10-28 11:36:13 +01:00
evgeny c31bdf74d8 Add host audio output controls for voice recorder failures 2026-10-28 11:36:13 +01:00
evgeny 5db51e64de Retry file resource cleanup when the core stops 2026-10-28 11:36:13 +01:00
evgeny a8c9bc6049 Document file browser lifecycle and export error handling 2026-10-28 11:36:13 +01:00
evgeny 0aa63c98ee Document Android file framing and error status contracts 2026-10-28 11:36:13 +01:00
evgeny 5290a2868d Preserve file wake lock ownership and isolate cleanup errors 2026-10-28 11:36:13 +01:00
evgeny 4f06b4bca9 Reproduce file cleanup failures and verify native cancellation 2026-10-28 11:36:13 +01:00
evgeny f60390c99c Model native file failures and wake lock ownership on host 2026-10-28 11:36:13 +01:00
evgeny 529237dfc8 Add host document providers for file failure tests 2026-10-28 11:36:13 +01:00
evgeny 84e4667f5c Describe avatar gallery and EXIF decoding behavior 2026-10-28 11:36:13 +01:00
evgeny 81f36d15c8 Clarify avatar editor ownership and UI publication state 2026-10-28 11:36:13 +01:00
evgeny 977992e834 Document Android avatar storage and publication contracts 2026-10-28 11:36:13 +01:00
evgeny 6f8baf82c7 Clarify Android playback recovery and diagnostics contracts 2026-10-28 11:36:13 +01:00
evgeny 00f8d8aeb0 Document Android call audio I/O and clock contracts 2026-10-28 11:36:13 +01:00
evgeny 7e502f9dd3 Verify headless server link commands and self-add rejection 2026-10-28 11:17:28 +01:00
evgeny 52dadf8b23 Document server link generation and channel addition commands 2026-10-28 11:13:34 +01:00
evgeny f1ff394f83 Document server authorization contract and cover cancellation lifecycle 2026-10-28 11:10:27 +01:00
evgeny bc296af99f Test server link presentation and authorization errors in clients 2026-10-28 11:07:58 +01:00
evgeny 3daacc07b7 Select any joined channel when opening an Android server link 2026-10-28 11:06:24 +01:00
evgeny f2d6561509 Route Android server links through channel selection and ordinary JOIN request 2026-10-28 11:05:23 +01:00
evgeny a9cc6785a9 Expose authorized server addition to Android JNI 2026-10-28 11:04:56 +01:00
evgeny f606c65858 Choose a local channel when opening a server link 2026-10-28 11:03:18 +01:00
evgeny 031b8b086b Accept server links in channel invitation dialog 2026-10-28 11:03:00 +01:00
evgeny 667cd1b302 Expose server link kind and authorization failures in Qt 2026-10-28 11:02:59 +01:00
evgeny 3c2c8978df Test authorized server JOIN over UDP and persistent addition keys 2026-10-28 11:01:35 +01:00
evgeny 3bc3e86529 Expose server links and channel addition through headless control 2026-10-28 10:59:16 +01:00
evgeny 7374b59c03 Authorize server join requests and run ordinary channel JOIN 2026-10-28 10:58:25 +01:00
evgeny 759a576a8d Build server links from shared codec and published endpoints 2026-10-28 10:56:09 +01:00
evgeny 0b6a882480 Persist generated server addition credentials in configuration 2026-10-28 10:55:50 +01:00
evgeny bd50140d26 Add explicit server and channel link kinds to shared codec 2026-10-28 10:55:25 +01:00
evgeny b773656dad Fix Windows entry point definitions in desktop GUI tests 2026-10-28 01:51:09 +01:00
evgeny 1ad00c12ad Fix attachment sending, media manifests and storage defaults 2026-10-28 01:47:17 +01:00
evgeny b86dcdd926 Fix member detail test bridge stubs after member editing API changes 2026-10-28 01:20:18 +01:00
evgeny 0ce248eb4a Configure recording compressor and provide a valid shutdown test identity 2026-10-28 00:59:00 +01:00
evgeny 65f39b6bae Test compressed recording rejection and ordered MainWindow shutdown 2026-10-28 00:59:00 +01:00
evgeny fee528194b Handle the tracked voice view during destruction and isolate test startup work 2026-10-28 00:59:00 +01:00
evgeny f624fd6a75 Clarify SQLite snapshot lifetime during desktop teardown 2026-10-28 00:59:00 +01:00
evgeny 15ca1047ce Cover desktop queue, attachment, DM, SQLite and media regressions 2026-10-28 00:59:00 +01:00
evgeny 9ee64d9a9f Extend desktop command regression suite and verify SQLite stopping handoff 2026-10-28 00:59:00 +01:00
evgeny 72f4258410 Replace stale desktop architecture documentation and honor the temporary directory 2026-10-28 00:59:00 +01:00
evgeny b4553db769 Reset selected GUI state during teardown and keep CHAT read watermarks separate from PM sequences 2026-10-28 00:59:00 +01:00
evgeny d5f5cf407a Finish desktop header ownership, state and model role contracts 2026-10-28 00:59:00 +01:00
evgeny 17772163cd Complete MainWindow and MessageList contracts for commands and snapshots 2026-10-28 00:59:00 +01:00
evgeny 7556695cc5 Guard desktop modal owners and remove obsolete message helpers 2026-10-28 00:59:00 +01:00
evgeny 8b2b68d383 Own feedback requests and fence poll dialogs to their channel and lifetime 2026-10-28 00:59:00 +01:00
evgeny d0bf402824 Document checked desktop snapshots and require matching media click gestures 2026-10-28 00:59:00 +01:00
evgeny 0942bf3d24 Use the running profile database directory for desktop media paths 2026-10-28 00:59:00 +01:00
evgeny b87050900c Deduplicate channel voice playback and resolve encrypted media snapshots 2026-10-28 00:59:00 +01:00
evgeny 6adfe5cf13 Centralize owned attachment downloads and key auto-play by channel and row 2026-10-28 00:59:00 +01:00
evgeny 0d6fd63e8f Return attachment metadata as checked SQLite snapshots 2026-10-28 00:59:00 +01:00
evgeny 034df2939c Reject incomplete DB reads and clock voice progress from PCM outside paint 2026-10-28 00:59:00 +01:00
evgeny 1235f770eb Fence deferred message actions, release voice views and flush state before shutdown 2026-10-28 00:59:00 +01:00
evgeny adefef675c Detach GUI SQLite readers before worker teardown 2026-10-28 00:59:00 +01:00
evgeny ce133a6acf Remove obsolete desktop DB sync and GUI writes and enforce read-only queries 2026-10-28 00:59:00 +01:00
evgeny f87ee63a1d Preserve failed composer drafts and cancel PM submissions with a result 2026-10-28 00:59:00 +01:00
evgeny 9d48821af2 Own message list requests and acknowledge PM text persistence 2026-10-28 00:59:00 +01:00
evgeny 4c1512cb78 Release unsubmitted media resources and own desktop channel and PM requests 2026-10-28 00:59:00 +01:00
evgeny 707938d503 Bind remaining desktop commands atomically and cancel owned attachments 2026-10-28 00:59:00 +01:00
evgeny d9abb1f025 Exercise both native owners throughout concurrent radio rebinding 2026-10-28 00:59:00 +01:00
evgeny 6063d3eb2c Include the chat service API in the radio command fixture 2026-10-28 00:59:00 +01:00
evgeny 27388c1137 Link the radio command GUI test to Windows COM support 2026-10-28 00:59:00 +01:00
evgeny bc78e0889a Route MainWindow radio invitations through owned commands and test them 2026-10-28 00:59:00 +01:00
evgeny 0f36248d1e Own and bind desktop radio call commands inside the bridge 2026-10-28 00:59:00 +01:00
evgeny 87b971569e Check command ownership independently of the uasync timer pool 2026-10-28 00:59:00 +01:00
evgeny 85172f3ac0 Include miniaudio types for the settings test audio backend 2026-10-28 00:59:00 +01:00
evgeny 096c613666 Own MainWindow UI state requests through the settings bridge 2026-10-28 00:59:00 +01:00
evgeny 95e59df5c7 Complete call window header contracts and align test data rows 2026-10-28 00:59:00 +01:00
evgeny fd4f092c9a Decline incoming calls when closing their window and verify teardown 2026-10-28 00:59:00 +01:00
evgeny 9ef188b0d3 Link call command tests against the camera and codec modules 2026-10-28 00:59:00 +01:00
evgeny de60f8fb15 Translate call command queue errors 2026-10-28 00:59:00 +01:00
evgeny e23a7e27eb Test call command ownership, allocation failures and core rebinding 2026-10-28 00:58:59 +01:00
evgeny f3d18a57b5 Use owned call start and audio failure hangup from the main window 2026-10-28 00:58:59 +01:00
evgeny 299c1b86f8 Send call window actions through the owned bridge API 2026-10-28 00:58:59 +01:00
evgeny 4b4f48963e Own desktop call commands and bind them atomically to the core 2026-10-28 00:58:59 +01:00
evgeny 138f6071b0 Guard capture-only image queue and test publication without Multimedia 2026-10-28 00:58:59 +01:00
evgeny fe7cd73646 Document asynchronous desktop stream publication and settings 2026-10-28 00:58:59 +01:00
evgeny cb95cf7d27 Document desktop file and live player window contracts 2026-10-28 00:58:59 +01:00
evgeny cfa53af3a3 Translate video playback seek and read errors 2026-10-28 00:58:59 +01:00
evgeny 71f5cc9c94 Preserve early seek position and document playback lifecycle 2026-10-28 00:58:59 +01:00
evgeny e371cc4dd9 Cover audio tail pause, replay, seeking and queued EOF callbacks 2026-10-28 00:58:59 +01:00
evgeny ab37a06dad Follow PCM node completion and keep seeking and replay consistent 2026-10-28 00:58:59 +01:00
evgeny 7fe90be7b2 Expose PCM drain state and cursor while file playback waits at EOF 2026-10-28 00:58:59 +01:00
evgeny d8109770a0 Finish file playback only after video presentation and PCM drain 2026-10-28 00:58:59 +01:00
evgeny 4118149dbc Reproduce file playback completion before queued media is presented 2026-10-28 00:58:59 +01:00
evgeny 7b3fe48657 Verify caption updates preserve continuous H264 and Opus playback 2026-10-28 00:58:59 +01:00
evgeny 5286388ada Refresh multiview names without recreating stream tiles 2026-10-28 00:58:59 +01:00
evgeny 3ff5ca7009 Update live player captions independently of playback state 2026-10-28 00:58:59 +01:00
evgeny 9d2ddcc496 Reproduce stale stream captions without restarting playback 2026-10-28 00:58:59 +01:00
evgeny debd3b45ef Clarify preview validity and publisher audio state responsibilities 2026-10-28 00:58:59 +01:00
evgeny a03abcaa02 Describe multiview tile lifetime, navigation and retry contracts 2026-10-28 00:58:59 +01:00
evgeny 1f0c7483e0 Describe stream bridge ownership, asynchronous requests and snapshots 2026-10-28 00:58:59 +01:00
evgeny 3960e28638 Document portal capture setup, frame lifetime and deferred shutdown 2026-10-28 00:58:59 +01:00
evgeny d9eab97dee Describe cursor overlay coordinates, thread ownership and outcomes 2026-10-28 00:58:59 +01:00
evgeny 615bdda36e Document QP sampling and atomic stream source snapshot parsing 2026-10-28 00:58:59 +01:00
evgeny ce4ff084cc Target transfer allocation faults after the file dialog closes 2026-10-28 00:58:59 +01:00
evgeny e05df14371 Keep file lifecycle test data isolated and suppress expected poll stalls 2026-10-28 00:58:59 +01:00
evgeny 07d9c17dec Check empty file cancellation and keep test capture semantics aligned 2026-10-28 00:58:59 +01:00
evgeny 0419c83ab0 Use file bridge cancellation without browser forwarding helpers 2026-10-28 00:58:59 +01:00
evgeny b04b262174 Cancel file batch commands directly through the owned bridge 2026-10-28 00:58:59 +01:00
evgeny 59cd456386 Allow cancellation of an empty file operation as a no-op 2026-10-28 00:58:59 +01:00
evgeny ba44e243a9 Verify file command success against the real storage service 2026-10-28 00:58:59 +01:00
evgeny 83f8b0cbe2 Cover file snapshots, cancellation ownership and browser retries 2026-10-28 00:58:59 +01:00
evgeny 656d64ae74 Adapt member file browser capture tests to snapshot APIs 2026-10-28 00:58:59 +01:00
evgeny bc90e88e72 Complete file browser operations when command posting fails 2026-10-28 00:58:59 +01:00
evgeny 7d789f68d4 Own desktop file commands and report cancellation through Qt 2026-10-28 00:58:59 +01:00
evgeny 142278d651 Reproduce cancelled and rejected desktop file commands 2026-10-28 00:58:59 +01:00
evgeny 7a4ce5d476 Clarify member file snapshots and browser helper contracts 2026-10-28 00:58:59 +01:00
evgeny 897da82b35 Document desktop member file batch and browser contracts 2026-10-28 00:58:59 +01:00
evgeny 8a831a0ed5 Remove deleted media blocks from the desktop module inventory 2026-10-28 00:58:59 +01:00
evgeny 5b07edcd98 Remove unused legacy media block reader and splitter 2026-10-28 00:58:59 +01:00
evgeny 4d2b59cb20 Disconnect unused legacy media blocks from desktop builds 2026-10-28 00:58:59 +01:00
evgeny b7ca74d61d Clarify link callback captures and their lifetime requirements 2026-10-28 00:58:59 +01:00
evgeny 25f0e21fb9 Document history selection state and delegate, link and scrolling contracts 2026-10-28 00:58:59 +01:00
evgeny b95fd63c46 Clarify the frozen attachment snapshot and shared submission diagnostics 2026-10-28 00:58:59 +01:00
evgeny 73a5366f1c Make regression callback cleanup safe after failed assertions 2026-10-28 00:58:59 +01:00
evgeny 58c2b5644d Translate the shared channel send failure message 2026-10-28 00:58:59 +01:00
evgeny 939b458c33 Check synchronous attachment handlers cannot redirect or access a deleted composer 2026-10-28 00:58:59 +01:00
evgeny 45485f4fbc Use one owned channel submission path and preserve the emitting context 2026-10-28 00:58:59 +01:00
evgeny 195b9c5afb Keep send fault injection and callback lifetimes isolated in tests 2026-10-28 00:58:59 +01:00
evgeny 48a6f03d78 Cover channel send success, retry, cancellation and allocation failures end to end 2026-10-28 00:58:59 +01:00
evgeny 143fd51791 Transfer channel text requests through the owned composer bridge 2026-10-28 00:58:59 +01:00
evgeny 4d18a7015d Report cancelled composer submissions before releasing their owned requests 2026-10-28 00:58:59 +01:00
evgeny 3c5e52a630 Keep ordinary channel drafts until their correlated save result 2026-10-28 00:58:59 +01:00
evgeny 9be3c4af48 Reproduce ordinary draft loss and missing cancellation acknowledgments 2026-10-28 00:58:59 +01:00
evgeny 88760510da Document composer acknowledgments, attachment ownership and context snapshots 2026-10-28 00:58:59 +01:00
evgeny cdaad39cf2 Verify corrected emoji insertion through the real composer connection 2026-10-28 00:58:59 +01:00
evgeny 214af09510 Correct emoji catalog mappings and log selected Unicode bytes 2026-10-28 00:58:59 +01:00
evgeny 5f90557a36 Reproduce emoji label mismatches through real picker selections 2026-10-28 00:58:59 +01:00
evgeny d0755477f2 Clarify parentless emoji panel sizing and tab icon drawing 2026-10-28 00:58:59 +01:00
evgeny b5d4c2be8b Describe category tab rendering and palette behavior 2026-10-28 00:58:59 +01:00
evgeny 62175e04a8 Document emoji catalog side effects and picker icon lifetimes 2026-10-28 00:58:59 +01:00
evgeny 8fddf854de Verify member save requests owner shutdown if rollback remains open 2026-10-28 00:58:59 +01:00
evgeny 1515a37b8a Verify fresh role snapshots and admin transfer cancellation ownership 2026-10-28 00:58:59 +01:00
evgeny b78fd7a8e6 Match editable roles to the same owner version read from SQLite 2026-10-28 00:58:59 +01:00
evgeny bc5e6aa5a5 Document cancellation acknowledgments for member edit commands 2026-10-28 00:58:59 +01:00
evgeny 8f02e1ec2d Read member edit capabilities and fields in one GUI snapshot 2026-10-28 00:58:59 +01:00
evgeny 84bf74e034 Limit commit fault injection to the member save transaction 2026-10-28 00:58:59 +01:00
evgeny f11ab51ccc Check stale forms, read failures and member command memory ownership 2026-10-28 00:58:59 +01:00
evgeny 49cbfe1ae0 Block property saves without a successfully read member snapshot 2026-10-28 00:58:59 +01:00
evgeny d73d62db48 Reject rename saves when the initial nickname read failed 2026-10-28 00:58:59 +01:00
evgeny 2d79023c5e Verify member save rollback across nickname SQL and owner changes 2026-10-28 00:58:59 +01:00
evgeny 279d7da51c Name member save status widgets for regression checks 2026-10-28 00:58:59 +01:00
evgeny f537f302c6 Exercise member dialogs against a real worker and SQLite failures 2026-10-28 00:58:59 +01:00
evgeny 5842855583 Confirm atomic member property saves before closing the dialog 2026-10-28 00:58:59 +01:00
evgeny 7e412d950a Bind owned admin transfer requests to the selected database 2026-10-28 00:58:59 +01:00
evgeny be11fbb8b6 Keep rename dialog open until the core confirms its write 2026-10-28 00:58:59 +01:00
evgeny 096e721faa Return correlated member save and cancellation results to live GUI contexts 2026-10-28 00:58:59 +01:00
evgeny 1431507ac5 Save member nicknames and owner changes in one core transaction 2026-10-28 00:58:59 +01:00
evgeny 30a15f6cfd Document audio settings snapshots and device test behavior 2026-10-28 00:58:58 +01:00
evgeny 005d136dc7 Make Android microphone capture stoppable and cleanup resilient
Use nonblocking AudioRecord reads with data and timestamp deadlines. Serialize idempotent close, finish interrupted joins before release, isolate callback failures, and abort stereo fallback when partial-record cleanup fails.

Close failed shared readers to new subscriptions, roll back worker startup, isolate observers, preserve interrupt state, and release the last consumer exactly once. Add an independent capture-tests JVM module to the standard Android unit-test task.

Validation: 38 capture scenarios (25 AudioRecord plus 13 PCM/PTT), 455 JVM tests, assembleDebug, core build, and full check.sh (225 tests plus proxy/burst/load) passed.
2026-10-28 00:53:01 +01:00
evgeny 74035fc043 Recover Android media audio sessions with explicit resource ownership
Retry monitor and capture setup after invalidating failed attempts. Bind output leases and callbacks to registration identity, cancel confirmation timers, and keep hardware cleanup independent from device enumeration during call handoff.

Commit profiles only after successful storage writes, acquire mode ownership before Android side effects, and reject blocking operations on main or the control worker. Keep the app singleton backed by an isolated MediaAudioSession with a single executor.

Validation: 30 media session scenarios, 420 JVM tests, assembleDebug, core build, and full check.sh (225 tests plus proxy/burst/load) passed.
2026-10-28 00:28:42 +01:00
evgeny a6ae4df3ff Harden Android audio router lifecycle and route selection
Roll back failed startup, finish independent stop cleanup, invalidate stale device and Telecom callbacks, and serialize router mutations. Publish input/output targets after accepted selection and support retries of rejected requests.

Separate modern communication device selection from legacy SCO, refresh replaced descriptors, and support A2DP and USB input-only devices in per-track mode. Clarify routing and observer ownership contracts.

Validation: 45 router scenarios, 390 JVM tests, assembleDebug, core build, and full check.sh (225 tests plus proxy/burst/load) passed. Previous router fails 25 of the 30 new cases.
2026-10-27 23:53:21 +01:00
evgeny 0d45bdbad6 Own Android incoming call alerts and notification actions
Bind notification tokens to full call IDs and call kinds, cancel actions on stop, and reject decline callbacks after ringing ends. Serialize alert state on main and recover notification channel setup after Android API failures.

Keep sound independent of wake-lock and notification failures. Remove orphaned notifications on cold start, preserve idempotent alerts during duplicate delivery and language changes, and document lifecycle contracts.

Validation: 32 new lifecycle cases, 360 JVM tests, assembleDebug, core build, and full check.sh (225 tests plus proxy/burst/load) passed.
2026-10-27 23:31:56 +01:00
evgeny 5a6eabf4fc Fix Android alert profiles and playback resource ownership
Configure audio attributes before MediaPlayer preparation, keep vibration independent from sound failures, and guard loop/focus cleanup against stale callbacks. Preserve ringback players on repeated phase requests.

Add 35 alert lifecycle tests against real Kotlin sources with controlled Android API failures. Validation: 328 JVM tests, assembleDebug, core build, and full check.sh (225 tests plus proxy/burst/load) passed. Previous sources fail 32 of the 35 new cases.
2026-10-27 23:12:11 +01:00
evgeny f4ef949482 Guard Android radio configuration with worker-owned tasks 2026-10-27 22:41:30 +01:00
evgeny f71aff3e11 Document Android radio automatic capture and background window contracts 2026-10-27 21:58:02 +01:00
evgeny d6dc6234d5 Recover SIM observers without losing healthy subscription state 2026-10-27 21:49:15 +01:00
evgeny 6a38eaa4eb Compile the real SIM monitor in the Android host tests 2026-10-27 21:39:26 +01:00
evgeny 6e6260ab29 Add controlled Telephony fixtures for Android SIM monitoring 2026-10-27 21:35:45 +01:00
evgeny 142cc1a7a1 Verify Android phone state publishing and JNI restart recovery 2026-10-27 21:30:07 +01:00
evgeny 4859d03f29 Return Android phone state queue acceptance through JNI 2026-10-27 21:25:51 +01:00
evgeny 067c1cd496 Own queued Android phone state data within the worker lifetime 2026-10-27 21:23:18 +01:00
evgeny 2b55d9225a Cover Android phone command cancellation and publication ownership 2026-10-27 21:21:52 +01:00
evgeny 9e679462d4 Expose Android phone state posting through the C bridge API 2026-10-27 21:18:29 +01:00
evgeny b92727e66a Make proximity observation safe across failures and restarts 2026-10-27 20:57:24 +01:00
evgeny 0d3ffb8736 Add a host sensor fixture for ProximityManager lifecycle checks 2026-10-27 20:54:40 +01:00
evgeny da85971969 Verify CoreActivity against Android JNI and native activity modes 2026-10-27 20:44:34 +01:00
evgeny ed1f4d8ea8 Preserve pending CoreActivity intent when the native queue rejects a request 2026-10-27 20:39:19 +01:00
evgeny f941066934 Cover rejected activity commands at the native queue boundary 2026-10-27 20:11:15 +01:00
evgeny 61266986e5 Route bridge activity requests through the worker owner 2026-10-27 20:10:00 +01:00
evgeny 4bece684da Queue Android activity updates while holding the worker lifetime lock 2026-10-27 20:07:51 +01:00
evgeny 1ed110d47c Validate CoreActivity ownership before mutations and cache completed JNI requests 2026-10-27 20:02:55 +01:00
evgeny b3b04b4d5a Add regressions for CoreActivity thread ownership and request caching 2026-10-27 19:53:53 +01:00
evgeny 29e6c977f2 Document Android worker cancellation and shutdown ownership 2026-10-27 19:30:29 +01:00
evgeny 64c1019a52 Verify cancelled Android workers retain callbacks and keep SQLite owned by the core 2026-10-27 19:30:29 +01:00
evgeny aca5f806c1 Keep worker callbacks atomic and verify failed shutdown preserves owners 2026-10-27 19:16:30 +01:00
evgeny 823bae076f Run Android service shutdown off the main thread and await it before startup 2026-10-27 19:07:05 +01:00
evgeny d6ea893f16 Preserve bridge callbacks until native worker shutdown succeeds 2026-10-27 18:57:36 +01:00
evgeny d83d58c874 Keep Android shutdown independent of a retiring service 2026-10-27 18:55:29 +01:00
evgeny 1c82432de9 Own Android worker threads until cleanup and join finish 2026-10-27 18:52:46 +01:00
evgeny 69b87ef3ed Verify Android startup readiness with the main looper and native worker 2026-10-27 18:33:49 +01:00
evgeny 11b3ceaa9b Wait for Android core readiness before applying settings 2026-10-27 18:27:14 +01:00
evgeny 8e0090b54b Track Android startup until native core readiness is confirmed 2026-10-27 18:20:48 +01:00
evgeny a09b67a70f Fix the key regeneration job type in ChatViewModel 2026-10-27 18:10:09 +01:00
evgeny 848247bde6 Exercise Android identity regeneration through JNI on devices 2026-10-27 18:08:29 +01:00
evgeny 50ea132c15 Recreate the Android core when regenerating its identity 2026-10-27 18:05:06 +01:00
evgeny 2ff51d0016 Persist Android identities atomically before updating config 2026-10-27 17:51:41 +01:00
evgeny 02ec6a50a5 Verify config saves survive cancellation of their submitting scope 2026-10-27 17:35:26 +01:00
evgeny 44f6d8a5bc Verify partial node reads and reject malformed address rows 2026-10-27 17:27:04 +01:00
evgeny 30a205340a Build node diagnostics from one checked SQLite snapshot 2026-10-27 17:27:04 +01:00
evgeny dc1f3260e3 Add node page snapshot and SQL failure regressions 2026-10-27 17:27:04 +01:00
evgeny d582f2ea77 Clarify settings dialog drafts, save semantics and borrowed dependencies 2026-10-27 17:27:04 +01:00
evgeny 2dd0970295 Document storage, network and database settings page contracts 2026-10-27 17:27:04 +01:00
evgeny 65c6bbc03b Distinguish optimize SQL completion from integrity check results 2026-10-27 17:27:04 +01:00
evgeny 6ba86bb1df Add SQLite and Qt database maintenance regression tests 2026-10-27 17:27:04 +01:00
evgeny 5233513fcc Remove unused settings test scaffolding 2026-10-27 17:27:04 +01:00
evgeny 8323be7272 Cover settings string limits, snapshots and late allocation failures 2026-10-27 17:27:04 +01:00
evgeny e3b0eebc2b Eliminate borrowed save commands from the desktop settings dialog 2026-10-27 17:27:04 +01:00
evgeny 4d3b294ee9 Remove borrowed audio settings commands and duplicated serialization 2026-10-27 17:27:04 +01:00
evgeny a1f925c789 Transfer storage settings snapshots through the owned bridge API 2026-10-27 17:27:04 +01:00
evgeny f1f5d33788 Centralize owned settings and name requests in the GUI bridge 2026-10-27 17:27:04 +01:00
evgeny 05b0ef50e4 Add real desktop settings save ownership regression tests 2026-10-27 17:27:04 +01:00
evgeny 5382b686e9 Keep config snapshots and network diagnostics precise 2026-10-27 17:18:13 +01:00
evgeny 893e714422 Show a specific error when database reset cannot finish 2026-10-27 17:18:13 +01:00
evgeny 3b42547740 Report native Android database cleanup failures accurately 2026-10-27 17:18:13 +01:00
evgeny b8e7b18937 Serialize Android config transactions and await them through UI lifecycles 2026-10-27 17:18:13 +01:00
evgeny 3ba581770c Build Android configuration from one preferences and key snapshot 2026-10-27 17:18:13 +01:00
evgeny 482026e208 Add an application-owned queue for atomic Android config writes 2026-10-27 17:18:13 +01:00
evgeny 78f34a3617 Clarify stream resource and voice route ownership wording 2026-10-27 15:25:33 +01:00
evgeny 4dc02d74b8 Document sound manager recovery, session ownership and callback rules 2026-10-27 15:23:38 +01:00
evgeny 027a4b4d9e Clarify desktop voice recording and playback contracts 2026-10-27 15:21:31 +01:00
evgeny 22460a1259 Merge remote-tracking branch 'origin/master' 2026-10-27 15:18:21 +01:00
evgeny 8d8fe8d6bf Fix sound settings request ownership on rejection and cancellation 2026-10-27 15:13:26 +01:00
evgeny 821f1b8a92 Add sound settings request ownership regressions 2026-10-27 15:11:22 +01:00
evgeny 6d925fecd1 Serialize Android network snapshots across monitor and core lifecycles 2026-10-27 15:04:27 +01:00
evgeny e3aa7839ae Include socket refresh monitoring in isolated host tests 2026-10-27 15:04:27 +01:00
evgeny 97a899c0c3 Model delayed network callbacks and config workers in host tests 2026-10-27 15:04:27 +01:00
evgeny 7b526ba681 Own Android network activity registrations across start and stop 2026-10-27 15:04:27 +01:00
evgeny f89c1975f7 Expose network activity callbacks to the isolated Android host tests 2026-10-27 15:04:27 +01:00
evgeny 8a22afc42d Add controlled host fixtures for Android network listeners 2026-10-27 15:04:27 +01:00
evgeny a6ab797659 Document audio device lifetime and voice worker contracts 2026-10-27 14:47:59 +01:00
evgeny eab9223f39 Clarify audio queue, capture clock and PCM reserve contracts 2026-10-27 14:43:24 +01:00
evgeny 799a71d361 Merge remote-tracking branch 'origin/master' 2026-10-27 14:32:36 +01:00
evgeny c7dadb0539 Clarify optional audio period and PTT latch release wording 2026-10-27 14:31:31 +01:00
evgeny 4389b511bf Align audio ownership comments with lease and recovery behavior 2026-10-27 14:28:02 +01:00
evgeny 29e2afc3ce Describe shared audio capture and buffer tuning contracts 2026-10-27 14:27:20 +01:00
evgeny cb49b9d4a4 Complete desktop radio UI and audio engine contracts 2026-10-27 14:24:46 +01:00
evgeny fb461cd56c Keep merged message link range documentation concise 2026-10-27 14:23:59 +01:00
evgeny 7f0c080492 Validate saved Android socket ports before reuse 2026-10-27 14:22:32 +01:00
evgeny 080c7a5fd5 Clarify Android auto socket identity and port reuse contracts 2026-10-27 14:22:32 +01:00
evgeny 0fe14699b0 Document Android conversation targets and test message ID conversion 2026-10-27 14:22:32 +01:00
evgeny 3d48024fd8 Trim desktop message link punctuation in linear time 2026-10-27 14:22:32 +01:00
evgeny f04637a257 Keep Android message link parsing linear and validate authority 2026-10-27 14:22:32 +01:00
evgeny 3e96e429eb Preserve unsigned node IDs in Android invite previews
Encode JNI node IDs as decimal strings and decode both uint64 fields without floating point or signed parsing. Compare all invitation fields and binary contents. Cover boundary IDs, malformed JSON types, and model equality with nine JVM tests. Native build, invite codec/build tests, and both debug APK ABIs passed.
2026-10-27 14:22:32 +01:00
evgeny 254029be63 Merge remote-tracking branch 'origin/master' 2026-10-27 14:19:09 +01:00
evgeny b5063f435b Explain radio settings reload and publication ordering 2026-10-27 14:12:49 +01:00
evgeny 0bac2566c9 Merge remote-tracking branch 'origin/master' 2026-10-27 14:11:47 +01:00
evgeny 8a96e5d1c7 Verify radio settings order during reentrant reload 2026-10-27 14:10:53 +01:00
evgeny 2226f54a56 Invalidate stale radio settings requests on reload 2026-10-27 14:08:22 +01:00
evgeny b4186dfae3 Cover radio settings recovery across core restarts 2026-10-27 14:06:05 +01:00
evgeny 0132a984dd Describe bounded control flow and corrected monitor behavior 2026-10-27 14:01:25 +01:00
evgeny cb50e268a4 Update monitor usage and asynchronous TCP architecture docs 2026-10-27 14:00:49 +01:00
evgeny 89c27b8fca Clarify control Action replies and graph display contracts 2026-10-27 14:00:49 +01:00
evgeny 4daa0e7f6b Document monitor TX ownership, deadlines and subscription bounds 2026-10-27 13:59:42 +01:00
evgeny 9e0cd3eddf Test control backpressure, snapshot mutations and deferred cleanup 2026-10-27 13:56:03 +01:00
evgeny 5c2ba74e3e Document desktop PTT chords and portal lifecycle 2026-10-27 13:54:55 +01:00
evgeny ae594e1e1b Test bounded monitor TCP sends and graph reconnect behavior 2026-10-27 13:47:41 +01:00
evgeny 488d8a601f Apply control TCP backpressure and stream node snapshots by ID 2026-10-27 13:46:01 +01:00
evgeny e9391c9790 Clarify desktop video modes and encoder output contracts 2026-10-27 13:43:00 +01:00
evgeny b1510ab437 Describe camera worker lifecycle and capture signals 2026-10-27 13:39:12 +01:00
evgeny ce06fe242b Queue monitor TCP commands and validate matched responses 2026-10-27 13:38:40 +01:00
evgeny 0594be9513 Document camera IPC framing and shared buffer ownership 2026-10-27 13:38:07 +01:00
evgeny 2d12dfb975 Correct monitor graph units and refresh cleared channel values 2026-10-27 13:34:04 +01:00
evgeny 4f27ce35a5 Fix control Action acknowledgements and validate command payloads 2026-10-27 13:33:13 +01:00
evgeny 6fdba59885 Correct cache cleanup glob documentation 2026-10-27 13:32:12 +01:00
evgeny 2d255afa6c Document avatar manager jobs and Lights Out behavior 2026-10-27 13:29:54 +01:00
evgeny 8691608924 Clarify avatar cache and image viewer contracts 2026-10-27 13:27:55 +01:00
evgeny fd80b35f8f Merge remote-tracking branch 'origin/master' 2026-10-27 13:17:50 +01:00
evgeny 7eaeb0e2f9 Preserve documentation audit and Android bridge fixes 2026-10-27 13:17:22 +01:00
evgeny ae4fb89bef Keep validation errors visible after explicit join attempts 2026-10-27 12:57:20 +01:00
evgeny d730dee925 Use accurate shared join errors and preserve result status 2026-10-27 12:56:13 +01:00
evgeny fcbec01c07 Translate shared join and offer failure messages 2026-10-27 12:55:13 +01:00
evgeny 16a68652ae Add UI regression tests for join and offer result errors 2026-10-27 12:53:47 +01:00
evgeny eca03747b3 Log desktop join and offer results with request context 2026-10-27 12:53:21 +01:00
evgeny b62ca4093e Report precise avatar editor source validation failures 2026-10-27 12:30:21 +01:00
evgeny 6c1b429e91 Check avatar editor coordinates after EXIF rotation 2026-10-27 12:29:20 +01:00
evgeny d72a2c092e Log avatar preparation generation and teardown state 2026-10-27 12:28:12 +01:00
evgeny 90d6f78a9e Resolve Qt 5 collection deduction in avatar and settings code 2026-10-27 12:26:58 +01:00
evgeny f54aa17e55 Observe buttonless pointer moves to cancel interrupted crop drags 2026-10-27 12:25:03 +01:00
evgeny 803d5f6583 Trace crop pointer state when a drag loses its button 2026-10-27 12:23:12 +01:00
evgeny 8c30c8e6ce Isolate avatar preparation generations and guard reentrant signals 2026-10-27 12:19:31 +01:00
evgeny d307492d22 Cover avatar preparation cancellation and reentrant owner deletion 2026-10-27 12:17:06 +01:00
evgeny b95d3628bf Check crop preview rendering and interrupted drags 2026-10-27 12:15:17 +01:00
evgeny 0a69864d10 Guard avatar upload controls across nested file and crop dialogs 2026-10-27 12:15:17 +01:00
evgeny 9c782be562 Bound avatar crop geometry and protect asynchronous preview lifetime 2026-10-27 12:10:36 +01:00
evgeny bfc280310d Cover avatar crop input bounds and modal owner lifetime 2026-10-27 12:07:36 +01:00
evgeny c25ed7c243 Report readable causes for malformed avatar blobs 2026-10-27 11:57:30 +01:00
evgeny 138de8d446 Document retryable avatar snapshot read failures 2026-10-27 11:57:30 +01:00
evgeny 90a588cfc1 Separate unpublished avatars from malformed published storage 2026-10-27 11:57:30 +01:00
evgeny 7d4da3a54d Treat an unpublished avatar as a successful empty read 2026-10-27 11:57:30 +01:00
evgeny a701580d54 Exercise main window destruction inside channel settings exec 2026-10-27 11:57:30 +01:00
evgeny bd105c630d Validate avatar read recovery and bounded typed blobs 2026-10-27 11:57:30 +01:00
evgeny 6106fc1b5d Keep transient SQLite failures out of the avatar cache 2026-10-27 11:57:30 +01:00
evgeny 905d30ceaf Distinguish failed avatar reads from committed empty blobs 2026-10-27 11:57:30 +01:00
evgeny 95e88ac66f Reproduce avatar cache poisoning after a transient SQL read error 2026-10-27 11:57:30 +01:00
evgeny 9fdd2dc9fb Specify the native channel ID range in GUI contracts 2026-10-27 11:57:30 +01:00
evgeny d4a969dc38 Match channel IDs to the native signed integer range 2026-10-27 11:57:30 +01:00
evgeny cf4a209837 Own group avatar commands and preserve pending result identity 2026-10-27 11:57:30 +01:00
evgeny 6c0aa98508 Cover group avatar publication ownership and result correlation 2026-10-27 11:57:30 +01:00
evgeny ddb373d445 Exercise settings retries and deletion changes during confirmation 2026-10-27 11:57:30 +01:00
evgeny cba3f4f75a Translate channel settings availability and queue errors 2026-10-27 11:57:30 +01:00
evgeny 3c6200f9c3 Keep channel settings alive safely across the main window loop 2026-10-27 11:57:30 +01:00
evgeny 74bcf91407 Own channel settings requests and guard nested dialogs 2026-10-27 11:57:30 +01:00
evgeny 271cfcd2f8 Cover channel settings queue failures and nested dialog lifetime 2026-10-27 11:57:30 +01:00
evgeny f12c7d072a test(chat): read complete media manifests with JSON whitespace 2026-10-27 11:48:09 +01:00
evgeny 9b24c1f012 fix(chat): preserve media and local state on incomplete database reads 2026-10-27 11:48:09 +01:00
evgeny 7c050eb7ef fix(chat): publish complete peer caches and clean pending JOIN state 2026-10-27 11:48:09 +01:00
evgeny ce3287ac94 fix(chat): verify incoming JOIN profiles before local insertion 2026-10-27 11:48:09 +01:00
evgeny 054ade0dcd fix(chat): select invite peers and read signed addresses consistently 2026-10-27 11:48:09 +01:00
evgeny 1efd8fb26c fix(chat): validate headless requests and complete media replies safely 2026-10-27 11:48:09 +01:00
evgeny c73090759f fix(chat): commit global names with signed node and member profiles 2026-10-27 11:48:09 +01:00
evgeny 0656f24a7c fix(chat): own Whisper jobs per instance and defer route UI events 2026-10-27 11:48:09 +01:00
evgeny cb9c04ff61 test(chat): distinguish route event deletion flag from routing API 2026-10-27 11:48:09 +01:00
evgeny 33556fefea test(chat): exercise channel deletion from a topology notification 2026-10-27 11:48:09 +01:00
evgeny 189ae43a7c docs(chat): distinguish committed core readiness from complete service startup 2026-10-27 11:48:09 +01:00
evgeny a4edd34695 fix(chat): retain SQL error codes when SQLite supplies no message 2026-10-27 11:48:09 +01:00
evgeny e28386c868 fix(chat): reject outer transactions before preparing shared service resources 2026-10-27 11:48:09 +01:00
evgeny 8151fc5a9c test(chat): cover startup admission, saved channel activation, and owner-close recovery 2026-10-27 11:48:09 +01:00
evgeny 1c6d203754 fix(chat): diagnose channel catalog failures with SQL status and shape 2026-10-27 11:48:09 +01:00
evgeny fb7846780b test(chat): verify startup metadata rollback and required callback allocation failures 2026-10-27 11:48:09 +01:00
evgeny 3b0ae79527 refactor(chat): keep the chat identity bound to its core instance 2026-10-27 11:48:09 +01:00
evgeny 6c777d4426 fix(chat): reject inconsistent repeated core initialization 2026-10-27 11:48:09 +01:00
evgeny 63406a9742 refactor(chat): borrow SQLite exclusively from the running core 2026-10-27 11:48:09 +01:00
evgeny 6f9723f8ce fix(chat): commit startup metadata before activating channels and publishing readiness 2026-10-27 11:48:09 +01:00
evgeny e3bd66f0b7 test(chat): reproduce ready startup after a required subscription fails 2026-10-27 11:48:09 +01:00
evgeny ed00f1ad9a fix(chat): require both member notification subscriptions at startup 2026-10-27 11:48:09 +01:00
evgeny 1aface994f fix(routing): report nodeinfo subscription allocation failure 2026-10-27 11:48:09 +01:00
evgeny 6429d4ca23 Merge desktop audit with updated chat contracts
Keep the complete member snapshot limit at 65535 and preserve SQL finalization checks, unsigned sorting, and owned GUI commands. Retain dynamic ETCP diagnostics with checked event lengths and no partial event on allocation failure. Validated three native and six GUI test targets and rebuilt vibechat.
2026-10-27 11:12:51 +01:00
evgeny c7618ba62b Limit group autoconnect indicators to group rows 2026-10-27 10:59:43 +01:00
evgeny 20ffa3fc6c Include the channel event byte type explicitly 2026-10-27 10:59:01 +01:00
evgeny 842083cdeb Exercise valid and stale channel menu actions 2026-10-27 10:57:21 +01:00
evgeny 1e3633ee56 Document channel list lifetime and validate row counters 2026-10-27 10:56:43 +01:00
evgeny 8552cf8316 Update isolated channel consumers for owned bridge requests 2026-10-27 10:56:43 +01:00
evgeny abc2f8efb6 Preserve channel state and own presence requests safely 2026-10-27 10:55:11 +01:00
evgeny 4d4fafc00b Isolate channel request cancellation from core startup tasks 2026-10-27 10:54:26 +01:00
evgeny 50fff66412 Cover channel reload state and pending request ownership 2026-10-27 10:53:23 +01:00
evgeny f81f6299b4 Bound channel row painting and support pixel-sized fonts 2026-10-27 10:51:20 +01:00
evgeny 282bf99d4a Cover channel delegate paint bounds and pixel fonts 2026-10-27 10:50:18 +01:00
evgeny 2822fa53e3 Clarify member snapshot output and boundary test contracts 2026-10-27 10:44:53 +01:00
evgeny 6104086d5b Bound member snapshot events and sort roster without quadratic copies 2026-10-27 10:37:33 +01:00
evgeny 34a95b7733 Route member diagnostics safely across panels and modal actions 2026-10-27 10:20:07 +01:00
evgeny a8958865bc Keep member rows consistent and own queued refresh requests 2026-10-27 09:48:38 +01:00
evgeny 6390c5db6a docs(chat): record preference full suite and GUI persistence validation 2026-10-27 07:37:41 +01:00
evgeny ee37cf0a55 docs(chat): record committed preference behavior and regression evidence 2026-10-27 07:34:44 +01:00
evgeny 655733e272 docs(chat): define preference return codes and bounded trampoline inputs 2026-10-27 07:33:08 +01:00
evgeny 89e2a2f22b test(chat): reject a valid signed profile stored with the wrong SQLite type 2026-10-27 07:31:16 +01:00
evgeny 9342795008 fix(chat): check stored text types before SQLite converts their values 2026-10-27 07:31:16 +01:00
evgeny fe5cf910e1 test(chat): cover preference read errors and all queued sound form values 2026-10-27 07:29:48 +01:00
evgeny 09e3ba62ef test(chat): verify preference rollback, committed sound delivery, and request validation 2026-10-27 07:27:44 +01:00
evgeny fdb0381f5c fix(gui): retain sound preference keys until the queued request is copied 2026-10-27 07:25:26 +01:00
evgeny 81fdbf90e1 fix(chat): skip initial sound publication when preference reading fails 2026-10-27 07:25:26 +01:00
evgeny fec2cecdb3 fix(chat): commit UI preferences before reporting or broadcasting them 2026-10-27 07:24:30 +01:00
evgeny 5360453960 test(chat): reproduce committed UI state after a finalization error 2026-10-27 07:22:45 +01:00
evgeny 34e729d988 docs(chat): record owner editor fault matrix and cross-platform validation 2026-10-27 07:21:26 +01:00
evgeny 11135283e7 docs(chat): document canonical owner versions and atomic editor behavior 2026-10-27 07:17:23 +01:00
evgeny c8e1d120ba fix(android): include the owner block size contract for role parsing 2026-10-27 07:16:37 +01:00
evgeny 104b702653 test(chat): inject owner editor allocation failures before commit 2026-10-27 07:15:15 +01:00
evgeny be311cf144 test(chat): include the member display contract explicitly 2026-10-27 07:13:41 +01:00
evgeny 9e10f7a357 test(chat): cover long role histories and deletion from owner commit callbacks 2026-10-27 07:13:19 +01:00
evgeny 6224c017da fix(chat): reject truncated or malformed stored owner JSON before comparison 2026-10-27 07:13:19 +01:00
evgeny a14fdf6d83 test(chat): cover owner edit conflicts, retry isolation, histories, and GUI patches 2026-10-27 07:12:13 +01:00
evgeny 98741e47d8 docs(chat): define owner editor conflict, history, and patch contracts 2026-10-27 07:09:50 +01:00
evgeny e3ea2ef78f fix(chat): preserve unedited GUI tags and read complete role histories 2026-10-27 07:08:33 +01:00
evgeny b7f799ebe5 test(chat): target the complete owner snapshot query 2026-10-27 07:07:30 +01:00
evgeny cde8c7b8e5 fix(chat): commit owner edits against a locked baseline and retain retry state 2026-10-27 07:06:09 +01:00
evgeny a9618169ab fix(chat): load complete verified owner snapshots and validate editor input 2026-10-27 07:04:28 +01:00
evgeny 16d7fc4fb5 fix(chat): validate owner versions and complete member reads before mutation 2026-10-27 07:02:44 +01:00
evgeny 91fb996a09 test(chat): reproduce owner editor load after SQL finalization error 2026-10-27 07:02:03 +01:00
evgeny f0d864bfd9 docs(chat): record profile full suite and sanitizer fixture correction 2026-10-27 07:00:13 +01:00
evgeny 59d8065fae test(chat): clear borrowed fault selector before its scope ends 2026-10-27 06:58:14 +01:00
evgeny 247952e9ed docs(chat): record signed profile transactions and callback fault coverage 2026-10-27 06:56:56 +01:00
evgeny 8bf09d9513 docs(sqlite): clarify verified node and owner write failures 2026-10-27 06:55:54 +01:00
evgeny f66c4e928e fix(member-files): preserve the original lookup error in ACL diagnostics 2026-10-27 06:50:02 +01:00
evgeny cce633b5b0 test(chat): reject negative owner results before checking change flags 2026-10-27 06:48:29 +01:00
evgeny beac8afba8 test(chat): cover profile trust, owner rollback, avatar policy, and startup failure 2026-10-27 06:46:15 +01:00
evgeny ecb589c670 test(chat): exercise atomic profile updates, no-ops, and callback deletion 2026-10-27 06:42:32 +01:00
evgeny ebb89e1bc3 test(chat): add profile transaction faults and committed notification observer 2026-10-27 06:39:57 +01:00
evgeny 70a4c669dc test(chat): verify nested member callback cancellation and namespace lifetime 2026-10-27 06:37:09 +01:00
evgeny f1d80922c7 fix(chat): fail startup when the JOIN apply subscription cannot be installed 2026-10-27 06:35:37 +01:00
evgeny 64adb799e9 fix(chat): retain member notification data across callback cancellation 2026-10-27 06:35:37 +01:00
evgeny 6efe3000d0 fix(chat): verify existing JOIN before signing local profile updates 2026-10-27 06:27:01 +01:00
evgeny 3195167ff3 fix(chat): commit signed profile updates under one version lock 2026-10-27 06:23:48 +01:00
evgeny 1cc60a3079 fix(json): decode Unicode escapes without losing subsequent profile fields 2026-10-27 06:21:05 +01:00
evgeny 20c095f2f3 fix(chat): preserve member transaction boundaries when rollback fails 2026-10-27 06:15:20 +01:00
evgeny b52e5f5489 fix(chat): validate complete signed profile before publishing read output 2026-10-27 06:13:12 +01:00
evgeny 30d58a4bde test(chat): reproduce successful signed profile read after finalization error 2026-10-27 06:12:04 +01:00
evgeny 1843a492bc docs(chat): record full JSON export validation 2026-10-27 06:07:29 +01:00
evgeny 463041a87f docs(chat): describe complete JSON exports and listing failure tests 2026-10-27 06:06:55 +01:00
evgeny cb0b71aec1 test(chat): roundtrip every ASCII control byte in channel JSON 2026-10-27 06:00:15 +01:00
evgeny f5270db52b test(chat): verify lossless JSON, corrupted rows, and deferred channel visibility 2026-10-27 05:58:08 +01:00
evgeny 92317bf383 test(chat): add JSON SQL faults and exact-capacity contract checks 2026-10-27 05:56:46 +01:00
evgeny 29e15254a1 fix(chat): reject truncated SQLite text in exported JSON 2026-10-27 05:53:11 +01:00
evgeny d5070a5df6 fix(chat): return complete escaped JSON and propagate listing SQL failures 2026-10-27 05:51:26 +01:00
evgeny 5fe66585b6 test(chat): reproduce invalid JSON for a signed channel name 2026-10-27 05:49:58 +01:00
evgeny 774fb66bb9 docs(chat): record full member and diagnostics validation 2026-10-27 05:46:06 +01:00
evgeny cfe4c24584 docs(chat): record member, mute, and diagnostics audit evidence 2026-10-27 05:42:28 +01:00
evgeny cec3e27aab test(chat): make diagnostic name expectation explicit in member fixture 2026-10-27 05:40:10 +01:00
evgeny 5af4572ae1 test(chat): verify invalid requests and diagnostic name lookup failures 2026-10-27 05:39:05 +01:00
evgeny 618c68268c docs(chat): specify complete member snapshots and committed local mute 2026-10-27 05:38:07 +01:00
evgeny 41b3503398 fix(chat): bound diagnostic counters and invalid mute request parsing 2026-10-27 05:37:05 +01:00
evgeny fd4c13f219 test(chat): give diagnostic links a valid empty ACK queue 2026-10-27 05:35:27 +01:00
evgeny a9bc410aad test(chat): include complete ETCP types for diagnostic fixture 2026-10-27 05:34:32 +01:00
evgeny 7279967a29 test(chat): cover member limits, radio commits, and large diagnostics 2026-10-27 05:33:33 +01:00
evgeny 8de9cfb1d2 fix(chat): build complete diagnostics with checked buffers and SQL results 2026-10-27 05:31:19 +01:00
evgeny 2504dd0b40 test(chat): add member SQL and committed radio state observers 2026-10-27 05:29:34 +01:00
evgeny 1bb824fb8a fix(chat): commit radio mute before applying cache and reporting success 2026-10-27 05:24:47 +01:00
evgeny 32a8c1c48b fix(chat): publish complete member snapshots after checked SQL finalization 2026-10-27 05:23:17 +01:00
evgeny 958feb4e75 test(chat): reproduce successful member snapshot after finalization failure 2026-10-27 05:22:09 +01:00
evgeny d3c5565c91 docs(chat): record full avatar suite and sanitizer results 2026-10-27 05:20:30 +01:00
evgeny 63c92840e2 docs(chat): mark avatar audit fixes complete with targeted verification 2026-10-27 05:19:14 +01:00
evgeny 32c89c7110 docs(chat): record avatar failure reproduction and transaction validation 2026-10-27 05:16:43 +01:00
evgeny ae74b621c8 docs(chat): specify avatar transaction, failure, and callback lifetime contracts 2026-10-27 05:15:12 +01:00
evgeny 2c691f98f7 test(chat): include EVP declarations explicitly in avatar SQL fixture 2026-10-27 05:13:08 +01:00
evgeny e8b913a351 test(chat): cancel avatar peers from the committed receive callback 2026-10-27 05:12:49 +01:00
evgeny 65409f8c80 test(chat): exercise avatar transaction, schema, and key lookup failures 2026-10-27 05:12:35 +01:00
evgeny 8b16f40094 test(chat): add precise avatar SQL fault hooks and committed-state observer 2026-10-27 05:11:03 +01:00
evgeny e645ef309a fix(member-files): reject membership lookup binding and finalization errors 2026-10-27 05:09:44 +01:00
evgeny e0598ccc22 fix(chat): commit avatar updates before notification and validate SQL reads 2026-10-27 05:08:31 +01:00
evgeny bc41bb68b6 test(chat): reproduce successful avatar publication after failed hash binding 2026-10-27 05:05:40 +01:00
evgeny f378c7b28d docs(chat): record full channel creation validation 2026-10-27 05:04:46 +01:00
evgeny 04ce61e3ca docs(chat): describe atomic channel creation and verified failure paths 2026-10-27 05:02:28 +01:00
evgeny 8003413d97 test(chat): cover channel input contracts and TCP creation result 2026-10-27 05:00:27 +01:00
evgeny f1cada4c02 Cover channel crypto failures and require owner close after failed rollback 2026-10-27 04:49:39 +01:00
evgeny 01c2ebd7d8 Verify channel SQL failure rollback and complete signed profiles through an independent reader 2026-10-27 04:43:31 +01:00
evgeny 1d84765f08 Instrument channel creation SQL and hash committed schema, identities and roots 2026-10-27 04:40:36 +01:00
evgeny 60942e542b Propagate all member block binding and finalization failures before index publication 2026-10-27 04:36:09 +01:00
evgeny 1ce58cbeac Reject publication when the initial member profile signature cannot be bound 2026-10-27 04:34:57 +01:00
evgeny 956febe1d7 Report committed channel creation results through the headless API 2026-10-27 04:27:31 +01:00
evgeny 129fece0af Share channel description verification with JOIN and cleanse owned creation requests 2026-10-27 04:27:31 +01:00
evgeny 55e270898b Check channel key generation and return the committed channel identity 2026-10-27 04:26:43 +01:00
evgeny 72b3068a8b Commit new channel identity and signed root membership before runtime publication 2026-10-27 04:25:08 +01:00
evgeny c0aacb3287 Define one bounded channel description encoding for signing and verification 2026-10-27 04:23:22 +01:00
evgeny 6a6ad5c612 Store channel metadata and peer schema atomically with checked SQL operations 2026-10-27 04:19:14 +01:00
evgeny 999fe909e4 Target the exact signed JOIN body instead of counting unrelated signatures 2026-10-27 04:16:07 +01:00
evgeny a4dd4a10d5 Exercise failed root signing during channel creation against committed SQLite 2026-10-27 04:12:58 +01:00
evgeny 1c5faaffc3 Record full feedback and poll verification after moving sanitizer artifacts 2026-10-27 04:06:52 +01:00
evgeny 9b55e3c7cb Record verified feedback rollback and poll command readback contracts 2026-10-27 04:02:56 +01:00
evgeny 6c0f9c9068 Reject embedded NUL before passing animation JSON to rlottie 2026-10-27 04:00:54 +01:00
evgeny 1b0034e1ba Handle saved-setting apply errors and document committed CLI interaction results 2026-10-27 03:58:19 +01:00
evgeny a7a7e4b5a1 Cancel member actions when a click becomes a drag 2026-10-27 03:54:03 +01:00
evgeny d741eb7374 Document feedback transaction ownership, codecs and committed readback acknowledgments 2026-10-27 03:52:09 +01:00
evgeny 7f0845e50c Check readback retries and refused acknowledgments keep feedback roots unchanged 2026-10-27 03:50:16 +01:00
evgeny 739ee0802f Verify poll commit acknowledgments survive snapshot faults and reserve memory before changes 2026-10-27 03:49:38 +01:00
evgeny 9876677a5f Refresh committed feedback without repeating user actions after readback errors 2026-10-27 03:49:38 +01:00
evgeny 1666538b0c Acknowledge committed poll commands when snapshot readback fails 2026-10-27 03:49:09 +01:00
evgeny 70251fafab Verify poll SQL failures preserve history, reactions, roots and events 2026-10-27 03:45:11 +01:00
evgeny 63e76d2cf5 Add targeted SQL read fault injection for poll command tests 2026-10-27 03:44:02 +01:00
evgeny 1820128f5b Document member badge painting and ignored state flags 2026-10-27 03:43:31 +01:00
evgeny efe879bfd9 Preserve complete audio frames and reject invalid ring buffers 2026-10-27 03:42:03 +01:00
evgeny aef6aae432 Validate complete poll command reads before publication or reaction changes 2026-10-27 03:41:36 +01:00
evgeny cf7a3a0939 Check SQL reads before interpreting poll targets and command fields 2026-10-27 03:41:06 +01:00
evgeny d89a86c9dd Cover feedback page and hash SQL errors without empty success 2026-10-27 03:38:21 +01:00
evgeny 7fa20ceb79 Specify shared FFmpeg image buffer ownership 2026-10-27 03:38:12 +01:00
evgeny 96a3d05c74 Reject failed feedback page and hash reads and report transaction error codes 2026-10-27 03:37:29 +01:00
evgeny fc94fa0bfd Own feedback version selection and page publication transactions 2026-10-27 03:35:03 +01:00
evgeny b0acb285c1 Bound TGS decoding and keep invalid icons out of animation 2026-10-27 03:33:50 +01:00
evgeny a591469770 Check feedback lookups and writes and retain rollback ownership 2026-10-27 03:33:34 +01:00
evgeny 1f19720cb8 Exercise feedback lookup failures, atomic retries and rollback ownership 2026-10-27 03:32:32 +01:00
evgeny 6a4fa8065a Add targeted SQL failure injection to real signed feedback tests 2026-10-27 03:30:51 +01:00
evgeny 1e5fc2d335 Record full 213-test verification and diagnose SQL clock fixture failure 2026-10-27 03:28:40 +01:00
evgeny 3309bee7eb Compare attachment SQL timestamps using the SQLite clock 2026-10-27 03:24:22 +01:00
evgeny 41ce04e2f0 Document desktop instance activation and lock lifetime 2026-10-27 03:22:21 +01:00
evgeny 795f930dd6 Record attachment index recovery and immutable settings verification 2026-10-27 03:22:19 +01:00
evgeny 55328e18af Clarify LAN adapter thread, delivery and settings contracts 2026-10-27 03:20:41 +01:00
evgeny 8fefd510a6 Document committed outbox retries and transaction-safe preparation recovery 2026-10-27 03:20:41 +01:00
evgeny dafd3a2adc Reject malformed audio diagnostic snapshots 2026-10-27 03:19:03 +01:00
evgeny 0995a1eac3 Complete event diagnostics and clarify attachment event payloads 2026-10-27 03:17:05 +01:00
evgeny 40ae782719 Cover settings immutability, validation rollback and LAN apply retry 2026-10-27 03:15:58 +01:00
evgeny 43f9608fbf Make chat settings reads immutable and validation failures atomic 2026-10-27 03:15:15 +01:00
evgeny 27aa76f914 Match recovery fixture byte count and normal cached-file policy 2026-10-27 03:14:09 +01:00
evgeny 9fa58b4f83 Keep desktop config projection separate from core settings 2026-10-27 03:14:00 +01:00
evgeny f6f3ca8da7 Share checked desktop config batches and diagnose write failures 2026-10-27 03:14:00 +01:00
evgeny bc11c6ac00 Check attachment initialization leaves an external transaction untouched 2026-10-27 03:12:56 +01:00
evgeny 52d8ec4e49 Preserve attachment files when shutdown sees an open transaction 2026-10-27 03:12:37 +01:00
evgeny 6bbd41f49f Exercise attachment recovery against uncommitted history deletion 2026-10-27 03:12:11 +01:00
evgeny 7f8869537b End idle attachment outbox scans without invoking commit hooks 2026-10-27 03:06:26 +01:00
evgeny 108266328c Commit attachment retry reservations before network delivery 2026-10-27 03:00:30 +01:00
evgeny b9d36b42af Report manifest limits and active download refusals precisely 2026-10-27 02:59:02 +01:00
evgeny 59d51d0e80 Document atomic attachment indexes and signed-history recovery 2026-10-27 02:58:44 +01:00
evgeny 13918d1cea Preserve desktop configuration on failed writes 2026-10-27 02:57:07 +01:00
evgeny 00c4065771 Use the signed-history limit for manual attachment parsing 2026-10-27 02:50:27 +01:00
evgeny 61ed80e18c Share the ETCP monitor across desktop entry points 2026-10-27 02:49:39 +01:00
evgeny 67368ebbac Check complete signed manifests beyond the old manual download limit 2026-10-27 02:46:59 +01:00
evgeny 2165c8a1f8 Exercise real manifest recovery and bounded backfill overflow 2026-10-27 02:38:02 +01:00
evgeny 7e7cabfb3a Verify atomic manifest indexes, local intent and history recovery 2026-10-27 02:34:02 +01:00
evgeny 78d0e3f54f Retry failed decryption after a newly verified download 2026-10-27 02:31:29 +01:00
evgeny b31f974a44 Target local attachment transactions and observe recovery timers in tests 2026-10-27 02:28:42 +01:00
evgeny 1b695fe247 Own and cancel desktop bridge commands before core teardown 2026-10-27 02:25:05 +01:00
evgeny fdb11ed3ce Restore retained attachment indexes during startup and manual download 2026-10-27 02:20:02 +01:00
evgeny d9f5da130e Recover attachment indexes from history without losing message events 2026-10-27 02:18:30 +01:00
evgeny fc60ca295a Commit attachment download intent and cache restoration atomically 2026-10-27 02:16:23 +01:00
evgeny 45d5aaa7a1 Index attachment manifests atomically and classify invalid identities 2026-10-27 02:15:14 +01:00
evgeny fe75a493ef Commit immutable attachment identity before message publication 2026-10-27 02:09:17 +01:00
evgeny 6803369a13 Record verified outgoing, completion and channel deletion fixes 2026-10-27 02:05:25 +01:00
evgeny 618f6ca073 Document atomic channel deletion and post-commit file cleanup 2026-10-27 01:55:35 +01:00
evgeny c3ac2059f4 Check complete Merkle cleanup before committing channel deletion 2026-10-27 01:55:03 +01:00
evgeny 8850121984 Verify channel deletion rollback and committed cascade snapshots 2026-10-27 01:53:47 +01:00
evgeny 6a6f8db208 Preserve channel files until checked metadata deletion commits 2026-10-27 01:50:03 +01:00
evgeny cd6ca2388f Cascade attachment records with channel deletion before cleaning files 2026-10-27 01:50:02 +01:00
evgeny 34e6fecbd0 Target completion transaction faults without affecting history jobs 2026-10-27 01:49:03 +01:00
evgeny 75124e0efa Preserve independent NAT details in desktop diagnostics 2026-10-27 01:48:13 +01:00
evgeny 12c5945eed Handle unavailable cores and late status page responses 2026-10-27 01:44:40 +01:00
evgeny 77e0a3c93e Verify completion ownership through cancellation, retry and task limits 2026-10-27 01:43:50 +01:00
evgeny b2addca5ce Clarify desktop logging contracts and retain early log path 2026-10-27 01:41:23 +01:00
evgeny d22bae19b4 Fix desktop node startup rollback and state ownership 2026-10-27 01:38:26 +01:00
evgeny d7ffa1031f Exercise committed decryption claims and retryable SQL completions 2026-10-27 01:37:30 +01:00
evgeny b71c3040d4 Claim decryption before workers and retry retained completions 2026-10-27 01:35:30 +01:00
evgeny 4d19de7cce Retain attachment completions until their SQL result commits 2026-10-27 01:34:47 +01:00
evgeny 851c6723ff Verify outgoing request persistence and document commit boundary 2026-10-27 01:30:24 +01:00
evgeny d1bfd1d16c Commit outgoing attachment requests before events and delivery 2026-10-27 01:28:23 +01:00
evgeny 023bd78e16 Cover atomic outgoing attachment request creation and timer guard 2026-10-27 01:27:19 +01:00
evgeny b163642b52 Fix oversized ETCP monitor snapshots 2026-10-27 01:26:16 +01:00
evgeny 8a0654e57b Merge remote-tracking branch 'origin/master' 2026-10-27 01:23:25 +01:00
evgeny e43bcec7cb Record verified REQUEST commit fix and continue chat audit 2026-10-27 01:22:57 +01:00
evgeny 383eb6d076 Describe atomic REQUEST acceptance and committed acknowledgment tests 2026-10-27 01:17:40 +01:00
evgeny bb961dd394 Exercise rejected REQUEST, author restart and real retry before ACK 2026-10-27 01:12:11 +01:00
evgeny 4d87cab28a docs(dm): align history generation contract after rebase 2026-10-27 01:11:28 +01:00
evgeny 5bb27d1b61 docs(dm): record completed contract audit and validation 2026-10-27 01:06:45 +01:00
evgeny 9480f8029b docs(dm): finish invite and cleanup validation contracts 2026-10-27 01:06:45 +01:00
evgeny a00db6229f docs(dm): reconcile architecture and PM delivery requirements 2026-10-27 01:06:45 +01:00
evgeny ad577318d9 docs(dm): specify media protocol and worker lifetime 2026-10-27 01:06:45 +01:00
evgeny 1cfafc43a4 docs(dm): complete mailbox and storage coordinator contracts 2026-10-27 01:06:45 +01:00
evgeny 2fe024fbbb docs(dm): clarify core and history ownership contracts 2026-10-27 01:06:45 +01:00
evgeny 98a6d3cce0 Test committed REQUEST acknowledgments, duplicates and SQL failures 2026-10-27 01:05:49 +01:00
evgeny 760398b96c Commit incoming attachment requests before acknowledging them 2026-10-27 01:02:55 +01:00
evgeny 492f6adc99 Merge upstream attachment audit documentation 2026-10-27 00:57:14 +01:00
evgeny 102da344d9 Merge origin/master with Android conversation gestures 2026-10-27 00:55:47 +01:00
evgeny 15ec41f2fd Record lost REQUEST after real acknowledgment and author rollback 2026-10-27 00:55:14 +01:00
evgeny 9f7ceb5815 Document REQUEST acknowledgment before external transaction commit 2026-10-27 00:55:13 +01:00
evgeny 13039933da android: separate avatar taps from conversation context menus 2026-10-27 00:49:00 +01:00
evgeny ef8e8f2cb5 Record verified author decision fix and close its audit task 2026-10-27 00:45:43 +01:00
evgeny 7649981cbc Describe committed author decisions and rollback lifecycle 2026-10-27 00:39:18 +01:00
evgeny 401193950b Verify author decision rollback and retry across real chat restart 2026-10-27 00:15:17 +01:00
evgeny 8c36d00fd2 Test atomic attachment decisions and committed UI notifications 2026-10-27 00:13:31 +01:00
evgeny 8a7f4469dc Commit author attachment decisions and delivery queue atomically 2026-10-27 00:10:58 +01:00
evgeny 77d6e8cfd0 Record reproduced attachment decision durability failures 2026-10-26 23:50:40 +01:00
evgeny 55ad0e971a Document uncommitted or undeliverable attachment author decisions 2026-10-26 23:49:35 +01:00
evgeny e6c0271e2c Record validated chat merge and stop the audit after Pull 2026-10-26 23:41:43 +01:00
evgeny 845bf2580d Merge upstream chat revisions with attachment transaction fixes 2026-10-26 23:35:21 +01:00
evgeny 012bd650ea Record verified GRANT fix before integrating upstream chat revisions 2026-10-26 23:22:57 +01:00
evgeny b8b6636644 Document result commit guarantees and verify quiesced callback removal 2026-10-26 23:17:55 +01:00
evgeny 9839f56f8c Exercise real GRANT retry and verify committed key before network ACK 2026-10-26 23:09:49 +01:00
evgeny 03d1afbd13 Tighten result regression snapshots and expose SQL transition diagnostics 2026-10-26 23:07:50 +01:00
evgeny 935bd704ae Test attachment result transaction failures and committed acknowledgments 2026-10-26 23:06:20 +01:00
evgeny 54a6e33c5e Commit attachment result state and key before acknowledging delivery 2026-10-26 23:03:19 +01:00
evgeny ab0b866c4c Explain edit rejection causes and unchanged submissions in diagnostics 2026-10-26 22:59:26 +01:00
evgeny 4b189891f7 Keep UI test references stable across queued channel refreshes 2026-10-26 22:58:15 +01:00
evgeny 5cf823da6a Record real-network GRANT bind failure and stop attachment audit 2026-10-26 22:57:20 +01:00
evgeny 334991fbe5 Initialize the desktop edit fixture with a valid test identity 2026-10-26 22:56:21 +01:00
evgeny 52651cfa0d Document confirmed GRANT acknowledgment without saved attachment key 2026-10-26 22:55:49 +01:00
evgeny 87f312f31b Retain startup diagnostics for the desktop edit integration test 2026-10-26 22:55:05 +01:00
evgeny b19e6797c9 Preserve Android edit drafts across screen recreation and serialize saves 2026-10-26 22:54:36 +01:00
evgeny e229811e20 Document editable history protocol and update media insert callback 2026-10-26 22:54:25 +01:00
evgeny aefef51c58 Update stress and media fixtures to sign versioned group records 2026-10-26 22:52:35 +01:00
evgeny 45257bf37f Exercise desktop editing through the real menu composer core and quoted replies 2026-10-26 22:51:10 +01:00
evgeny d998b390f3 Exercise offline and live edits over real Merkle and PUSH transport 2026-10-26 22:50:20 +01:00
evgeny ec8c6e9eb1 Verify edit events bypass new-message callbacks and notifications 2026-10-26 22:49:45 +01:00
evgeny 8523448c3a Reserve desktop edit dispatch and reject malformed update events 2026-10-26 22:49:45 +01:00
evgeny 5b6c96d3d8 Test desktop composer edit confirmation cancel failure and channel changes 2026-10-26 22:47:58 +01:00
evgeny 48bdb85ff9 Preserve composer media policy and display edit times for short or emoji text 2026-10-26 22:47:57 +01:00
evgeny 8b34889a19 Check signed reply references against the revision envelope 2026-10-26 22:46:42 +01:00
evgeny e45f33e7b5 Cover revision conflicts Merkle updates stale ACKs and rollback 2026-10-26 22:46:08 +01:00
evgeny 82ef6f282f Reset only dependent group history state when adopting editable format 2026-10-26 22:46:08 +01:00
evgeny 0a75a53ed9 Correct Android attachment submission argument after editor integration 2026-10-26 22:45:04 +01:00
evgeny c39bdef344 Localize group editing controls and edit timestamps 2026-10-26 22:45:04 +01:00
evgeny 030336eaeb Record verified attachment key fix lifecycle contracts and validation 2026-10-26 22:44:14 +01:00
evgeny d0ff7a81f7 Bind deferred-author integrity fixture to its signed author 2026-10-26 22:43:46 +01:00
evgeny 65cdb5b468 Keep format-reset rollback safe and expire pending revisions by edit time 2026-10-26 22:43:38 +01:00
evgeny cad10a33e0 Test group edit persistence references and scoped dev format reset 2026-10-26 22:42:36 +01:00
evgeny 93057c9eb7 Adapt signed history regression fixtures to canonical revision envelopes 2026-10-26 22:41:56 +01:00
evgeny 1afb1010cc Wire desktop context-menu editing and update visible messages in place 2026-10-26 22:38:42 +01:00
evgeny 2a9b5748e9 Show edited time and retain revision metadata in desktop rows 2026-10-26 22:38:17 +01:00
evgeny 20350338b8 Deliver committed edits to desktop without message notifications 2026-10-26 22:38:17 +01:00
evgeny e483027e3e Edit group text in desktop composer with save cancel and draft restoration 2026-10-26 22:38:06 +01:00
evgeny b46927f40d Read group revisions and keep history windows ordered by stable IDs 2026-10-26 22:37:39 +01:00
evgeny 371aa3ac19 Dispatch correlated edit submissions through shared composer request 2026-10-26 22:37:39 +01:00
evgeny ca15dbb88a Save authored text edits and preserve group references across revisions 2026-10-26 22:36:47 +01:00
evgeny 2f35502978 Expose group message editing and committed update event 2026-10-26 22:35:46 +01:00
evgeny 809f009796 Replicate group message revisions atomically with versioned acknowledgements 2026-10-26 22:35:34 +01:00
evgeny 5c638a60db Define permanent group message identity from creation fields 2026-10-26 22:33:43 +01:00
evgeny b0d246913d Complete Android navigation after PM conversation deletion 2026-10-26 22:11:39 +01:00
evgeny 18df7cc43d Describe media backfill triggers in terms of Merkle history sync 2026-10-26 22:11:39 +01:00
evgeny 9009153cc5 Remove unused legacy chat sync commands and empty connect API 2026-10-26 22:11:39 +01:00
evgeny 5dab86e840 Initialize chat schema before storing and publishing local identity 2026-10-26 22:11:39 +01:00
evgeny f6005fd96d Remove obsolete history chain reads from chat caches and API 2026-10-26 22:11:39 +01:00
evgeny f1da7d7ee8 Align desktop history reads with Merkle schema and fix PM test setup 2026-10-26 22:11:39 +01:00
evgeny cd0329b301 Cover deleted PM composer state and log GUI deletion failures 2026-10-26 22:11:39 +01:00
evgeny 8ccad3b56b Test PM deletion through the desktop window and history snapshot generations 2026-10-26 22:11:39 +01:00
evgeny e88f3ce46a Finish PM composer cleanup and skip history requests after shutdown 2026-10-26 22:11:39 +01:00
evgeny f83033d3a1 Guard Android PM history and pending deletion across asynchronous sends 2026-10-26 22:11:39 +01:00
evgeny 5778c8aa0a Translate desktop PM deletion confirmation and errors 2026-10-26 22:11:39 +01:00
evgeny 6382c794ea Complete desktop PM deletion after the core transaction result 2026-10-26 22:11:39 +01:00
evgeny 4089944673 Guard desktop PM sends and history by conversation generation 2026-10-26 22:11:39 +01:00
evgeny e10354a0ac Keep PM composer work bound to its history generation 2026-10-26 22:11:39 +01:00
evgeny df80c43a57 Offer conversation deletion in the desktop PM context menu 2026-10-26 22:11:39 +01:00
evgeny 8e3c536cbb Bridge desktop DM deletion requests and results 2026-10-26 22:11:39 +01:00
evgeny f0b7b22f92 Read visible DM generations in the desktop conversation list 2026-10-26 22:11:39 +01:00
evgeny fd82e7bf1b Tag DM history snapshots with conversation generation 2026-10-26 22:11:39 +01:00
evgeny 71dfc9d70d Clarify attachment commit ownership and SQL failure diagnostics 2026-10-26 22:10:44 +01:00
evgeny e5ca2e174c Honor core stop before and after Android restart with lifecycle regressions 2026-10-26 22:07:39 +01:00
evgeny c75bfc618a Honor core stop in desktop owner loop and verify cleanup 2026-10-26 22:07:39 +01:00
evgeny 07f63c3047 Document audited call video and session contracts 2026-10-26 21:54:18 +01:00
evgeny 289b592598 Use distinct regression helper name and reserved uasync post API 2026-10-26 21:53:36 +01:00
evgeny 99ebee37e7 Test attachment key commit faults ownership and retry with real workers 2026-10-26 21:51:36 +01:00
evgeny 549cc202fb Commit complete attachment preparation before accepting encryption work 2026-10-26 21:49:11 +01:00
evgeny d877e8881c Record confirmed attachment key bind failure and pause chat audit 2026-10-26 21:31:00 +01:00
evgeny e33d51a34a Document attachment key persistence failure during chat audit 2026-10-26 21:29:41 +01:00
evgeny 1899b7f8cf Record verified admin and worker rebase integration 2026-10-26 20:54:08 +01:00
evgeny 589fef2aae Reconcile audit contracts with upstream post cancellation 2026-10-26 20:48:15 +01:00
evgeny 8718ee901c Record verified worker shutdown fix and negative control 2026-10-26 20:46:31 +01:00
evgeny 2c48a53c6a Clarify cancellation ownership during service shutdown 2026-10-26 20:46:31 +01:00
evgeny 9e68928222 Test worker drain with completions in a detached batch 2026-10-26 20:45:32 +01:00
evgeny 781d41e003 Disable detached worker completions before draining jobs 2026-10-26 20:45:32 +01:00
evgeny 8f3d9edf8b Record admin verification and worker completion crash 2026-10-26 20:44:42 +01:00
evgeny 998993997d Diagnose admin key derivation failures without exposing secrets 2026-10-26 20:44:42 +01:00
evgeny 5169ffd0b3 Specify admin import transaction and notification contracts 2026-10-26 20:44:42 +01:00
evgeny cc04f1c0fa Test admin import rollback, commit notification and safe retry 2026-10-26 20:44:42 +01:00
evgeny 76527de44f Store admin keys atomically and reject invalid transfer context 2026-10-26 20:44:42 +01:00
evgeny e65ceeafdc Track atomic admin import correction and regression requirements 2026-10-26 20:44:42 +01:00
evgeny 1916ba4270 Document admin key import failures and null transfer crash 2026-10-26 20:44:42 +01:00
evgeny bc623f2371 docs(call): record post-rebase validation results 2026-10-26 20:30:18 +01:00
evgeny f521bb37f4 fix(call): align audio frontend ownership with core lifecycle
Keep the borrowed audio provider on UTUN_INSTANCE across chat service restarts.
Attach and detach Android voice from the core worker and reject DSP startup
after detach. Preserve TX owner epochs, pending slots and foreign-instance RX
isolation. Remove the unused cross-thread online API and keep its check local
to call.c.

Add eight lifecycle regressions with real cores and the Android host bridge.
Audit public call, DSP, clock, headless and desktop audio contracts and record
the findings and validation scope.

Validation: voice/desktop 38/38, four native call suites, native and both Android
ABI builds, full check 204/204 plus proxy/burst/load. JVM results remain Gradle
UP-TO-DATE (155 app and 15 router). No hardware runtime validation.
2026-10-26 20:22:46 +01:00
evgeny b84a6ab3b9 docs(call): record validated Bluetooth lifecycle fix and regressions 2026-10-26 20:22:27 +01:00
evgeny 2e8885548b docs(call): clarify Android output and Bluetooth proxy ownership 2026-10-26 20:21:58 +01:00
evgeny 83df895532 build(android): run router lifecycle regressions with app unit tests 2026-10-26 20:21:58 +01:00
evgeny f724703156 test(android): cover Bluetooth router teardown and callback races 2026-10-26 20:21:58 +01:00
evgeny 34133e4f6f test(android): isolate router application and logging fixtures 2026-10-26 20:21:58 +01:00
evgeny 8cbadd821f test(android): model Bluetooth proxy ownership and device callbacks 2026-10-26 20:21:58 +01:00
evgeny 161422b2cd test(android): add isolated host context and clock fixtures 2026-10-26 20:21:58 +01:00
evgeny de83d7bbf4 fix(android): own Bluetooth proxies across router lifecycle 2026-10-26 20:21:58 +01:00
evgeny 3987295707 Report exact DM SQL prepare errors without duplicate step failures 2026-10-26 19:50:03 +01:00
evgeny 497792da73 Commit exact DM custody tombstones before acknowledging deletion 2026-10-26 19:45:51 +01:00
evgeny 3f195c058b Retain DM coordinator bodies when assignment scans fail 2026-10-26 19:42:00 +01:00
evgeny 2fce4641ec Exercise DM cleanup SQL failures and durable ACK retries 2026-10-26 19:39:04 +01:00
evgeny 8642b04e6d Cover worker teardown with completions in the active post batch 2026-10-26 19:15:32 +01:00
evgeny 93ec12226f Cancel pending posts from active dispatch batches 2026-10-26 19:12:37 +01:00
evgeny 28a5d0509f Expire DM test custody only after confirmed storage 2026-10-26 18:42:45 +01:00
evgeny 25a8b905fc Accept verified DM originals after storage expiry 2026-10-26 18:42:45 +01:00
evgeny ab8713d88f Record post-rebase sync validation on current master 2026-10-26 18:34:45 +01:00
evgeny c5075354d0 Record completed sync audit scope and refresh historical design links 2026-10-26 18:27:49 +01:00
evgeny 1456f02c03 Reconcile completed member and Merkle documentation audit status 2026-10-26 18:27:49 +01:00
evgeny b48f9e7a19 Close history Merkle migration with final validation results 2026-10-26 18:27:49 +01:00
evgeny 750ccf638d Verify history migration results and checkpoint revision races 2026-10-26 18:27:27 +01:00
evgeny bf94b240c8 Wake the lifecycle fixture after asserting standby restoration 2026-10-26 18:27:27 +01:00
evgeny 7d6197b5eb Restore requested activity after forced-active stream regression 2026-10-26 18:27:27 +01:00
evgeny d532fe062e Avoid recursive standby retries on allocation failure 2026-10-26 18:27:27 +01:00
evgeny f92077e601 Isolate stream wake state and require full roots in sync stress 2026-10-26 18:27:27 +01:00
evgeny e00d1f5212 Diagnose Merkle source profiles and identify both exchange endpoints 2026-10-26 18:27:27 +01:00
evgeny 669ad86e57 Document shared history Merkle protocol and bounded transactions 2026-10-26 18:27:26 +01:00
evgeny df39999624 Initialize media history model and admit the purge test peer 2026-10-26 18:27:26 +01:00
evgeny 316bacd8c8 Share isolated history model setup across sync fixtures 2026-10-26 18:27:26 +01:00
evgeny f42f002eb1 Test atomic page rollback, late author keys and model run policy 2026-10-26 18:27:26 +01:00
evgeny fefc0ee003 Preserve Android standby retry waits and clarify history contracts 2026-10-26 18:27:26 +01:00
evgeny 0444a4bfd9 Resume admitted history peers and gate automatic Merkle work by policy 2026-10-26 18:27:26 +01:00
evgeny a7b556d9a8 Verify long equal-count history divergence converges by full roots 2026-10-26 18:27:26 +01:00
evgeny 2833c53644 Cover handshake RNG failures and diagnose mismatched round tokens 2026-10-26 18:27:26 +01:00
evgeny a46091cb19 Yield the event loop between bounded history maintenance batches 2026-10-26 18:27:26 +01:00
evgeny 3a4143183d Cover stable history cursors, deleted authors and bounded TTL cleanup 2026-10-26 18:27:26 +01:00
evgeny 3fe697e1a9 Log history pause and await verified roots in empty peer fixtures 2026-10-26 18:27:26 +01:00
evgeny d76eb067bb Preserve signed history through schema conversion and resume both peers 2026-10-26 18:27:26 +01:00
evgeny 1402413ab9 Exercise history Merkle roots over live peers and invitation recovery 2026-10-26 18:27:26 +01:00
evgeny a87ece370c Revalidate history peers after membership and cover preflight integrity 2026-10-26 18:27:26 +01:00
evgeny 012cbdcd49 Register history after shared Merkle startup and validate page cursors 2026-10-26 18:27:26 +01:00
evgeny e822f9fef7 Pass leaf bounds to immediate page models and report disconnects 2026-10-26 18:27:26 +01:00
evgeny 5e5ed41c19 Replace history chain exchange with canonical Merkle data model 2026-10-26 18:27:26 +01:00
evgeny 41c2a77fe6 Expose per-model work policy and checkpoint results for history 2026-10-26 18:27:26 +01:00
evgeny a079381c0a Test cancelled Merkle rounds against the fresh responder challenge 2026-10-26 18:27:26 +01:00
evgeny 45c282e0b7 Bind Merkle rounds to fresh initiator and responder tokens 2026-10-26 18:27:26 +01:00
evgeny 137e30ec82 Require a fresh responder token when reattaching Merkle sessions 2026-10-26 18:27:26 +01:00
evgeny d20f31c165 Plan canonical history reconciliation on the shared Merkle engine 2026-10-26 18:27:26 +01:00
evgeny 5ae5fd066d Close history integrity fixes and record remaining sync audit scope 2026-10-26 18:27:26 +01:00
evgeny 143788cdcd Document verified history deletion and message-specific delivery 2026-10-26 18:26:58 +01:00
evgeny aa97e053cd Ensure SQLite allocation failures cannot authorize history deletion 2026-10-26 18:26:58 +01:00
evgeny 7853fb0fc6 Keep chain reads and delivery confirmation failures explicit 2026-10-26 18:26:58 +01:00
evgeny 557c98aeae Cover history preservation, corruption cleanup and exact delivery ACKs 2026-10-26 18:26:58 +01:00
evgeny fd53b443a0 Preserve history on verification errors and identify delivery ACKs 2026-10-26 18:26:58 +01:00
evgeny 26432be0e4 Point delivery audit finding to the failing SQL statement 2026-10-26 18:26:58 +01:00
evgeny 6734035734 Record db_sync verification data loss, deletion policy and delivery SQL defect 2026-10-26 18:26:58 +01:00
evgeny 068eddefd8 Flag db_sync data loss on verification errors and invalid duplicate input 2026-10-26 18:26:31 +01:00
evgeny b0bf27de61 Close DM expiry fix with fault restart and sanitizer evidence 2026-10-26 18:06:14 +01:00
evgeny 9fe4e834fe Describe DM expiry reconciliation and await restarted test link 2026-10-26 18:02:29 +01:00
evgeny 59e694bd83 Check all SQL results during DM storage release 2026-10-26 17:54:45 +01:00
evgeny 5788d2557b Test DM release rollback and expiry recovery after restart 2026-10-26 17:54:45 +01:00
evgeny cb08faae04 Reconcile DM storage expiry and release assignments atomically 2026-10-26 17:49:26 +01:00
evgeny dda4a780e3 Document unreconciled DM media expiry after SQL failure 2026-10-26 17:42:45 +01:00
evgeny 3dc5eb502d Record post-rebase DM validation 2026-10-26 17:31:42 +01:00
evgeny 87d24b722b Document verified DM name normalization and regressions 2026-10-26 17:27:18 +01:00
evgeny d09ed0316f Preserve UTF-8 boundaries in DM peer names 2026-10-26 17:27:18 +01:00
evgeny fa76447f53 Close Android mute fix with native Android and full-suite verification 2026-10-26 17:14:58 +01:00
evgeny 79b06846c6 Test Android bridge mute after real AEC and AGC across unmute 2026-10-26 17:14:18 +01:00
evgeny 000b28027c Preserve Android raw capture through AEC and apply mute before Opus 2026-10-26 17:14:18 +01:00
evgeny bdaff406be Forward Android frame mute through the native capture bridge 2026-10-26 17:14:18 +01:00
evgeny f83e27260d Record rebased DM verification and UTF-8 name truncation defect 2026-10-26 17:07:18 +01:00
evgeny b6588d0594 Preserve DM state on database failures and document contracts 2026-10-26 16:55:20 +01:00
evgeny 03be46c339 Record desktop voice checks and reproduce Android mute signal after AEC 2026-10-26 16:34:23 +01:00
evgeny 5fee00c451 Clarify desktop voice contracts and document Android mute ordering defect 2026-10-26 16:31:11 +01:00
evgeny 54a7522dd9 Record headless PCM framing fix and full regression results 2026-10-26 16:08:35 +01:00
evgeny 0ad80f3906 Clarify frame assembly and keep reference PCM arithmetic signed 2026-10-26 15:58:11 +01:00
evgeny 7c4e6f9972 Test complete headless frames across queue and short-write boundaries 2026-10-26 15:55:08 +01:00
evgeny 913ae531ec Queue complete headless PCM frames and account for overflow drops 2026-10-26 15:51:35 +01:00
evgeny ae9d3f0103 Record headless PCM backpressure framing failure and repair plan 2026-10-26 15:35:03 +01:00
evgeny 45834692a7 Document headless PCM framing defect and independent codec ownership 2026-10-26 15:33:11 +01:00
evgeny 03b050949c Close radio mesh regression with full merged-branch verification 2026-10-26 15:16:13 +01:00
evgeny bf4d14c46e Guard mesh gate node indices before matching endpoints 2026-10-26 15:09:35 +01:00
evgeny 1bc27aa2ca Verify radio mesh deduplication independently of arrival order 2026-10-26 15:08:08 +01:00
evgeny ec795b4764 Explain false radio mesh failure and preserve rebase audit 2026-10-26 15:01:59 +01:00
evgeny ff394c7a6a Preserve final mesh duplicate read outside diagnostic mode 2026-10-26 14:57:41 +01:00
evgeny 21af2e0f35 Observe late mesh packets within the running event loop 2026-10-26 14:57:41 +01:00
evgeny d943c0ddca Poll diagnostic mesh tail after the original loop stops 2026-10-26 14:57:41 +01:00
evgeny c2908a6c58 Trace radio mesh packet paths and original stop conditions 2026-10-26 14:57:41 +01:00
evgeny 5587c60603 Record successful proxy integration checks after TX fix 2026-10-26 14:57:41 +01:00
evgeny faaa5a835a Record repeated full-check failure in unrelated radio mesh test 2026-10-26 14:57:41 +01:00
evgeny 2429688382 Document call audio TX fix and independent radio mesh flake 2026-10-26 14:57:41 +01:00
evgeny f0df3d8848 Make stale TX regressions assert observable behavior first 2026-10-26 14:57:24 +01:00
evgeny bbc9f750c3 Cover call audio TX ownership across lifecycle transitions 2026-10-26 14:57:24 +01:00
evgeny e11eca93bb Isolate call audio TX tasks by instance binding epoch 2026-10-26 14:57:24 +01:00
evgeny 266406261a Validate call audio ownership plan against lifecycle boundaries 2026-10-26 14:57:24 +01:00
evgeny a38b1f1e0b Record call audio audit scope and unchanged implementation checks 2026-10-26 14:57:24 +01:00
evgeny 6f8164d7cd Record call audio rebind counter defect and ownership plan 2026-10-26 14:57:24 +01:00
evgeny a4d8637f45 Document stale call audio tasks corrupting pending accounting 2026-10-26 14:57:09 +01:00
evgeny ea3685d8f5 Record final call admission contract and environment checks 2026-10-26 14:57:09 +01:00
evgeny c7387c2879 Record passing call admission and voice verification 2026-10-26 14:57:09 +01:00
evgeny 198cf52791 Document call admission fix and live regression coverage 2026-10-26 14:56:54 +01:00
evgeny 9838384d43 Authenticate admission fixture members for radio interaction 2026-10-26 14:56:54 +01:00
evgeny 56a06da35f Cover call admission, ID reuse and retained sessions on live cores 2026-10-26 14:56:54 +01:00
evgeny 96d99a183d Reject overlapping outgoing calls and registered call IDs 2026-10-26 14:56:54 +01:00
evgeny 7e69595372 Record call audit baseline checks and exact admission location 2026-10-26 14:56:54 +01:00
evgeny c5eb17e59b Record outgoing call admission defect and verification plan 2026-10-26 14:56:54 +01:00
evgeny aa09459c70 Document missing busy admission guard for outgoing calls 2026-10-26 14:56:06 +01:00
evgeny aea8ca7236 Close feedback admission fix with full integration and sanitizer verification 2026-10-26 14:44:03 +01:00
evgeny 1634499d84 Document active feedback, credential dependencies and permission round lifecycle 2026-10-26 14:44:03 +01:00
evgeny f3be00438b Assert profile updates leave feedback idle and preserve outer-commit change flags 2026-10-26 14:44:03 +01:00
evgeny 953e094c92 Restrict feedback invalidation to credential, key and admission changes 2026-10-26 14:44:03 +01:00
evgeny 5cae3d095d Keep the full-cursor comment beside its pagination test 2026-10-26 14:44:03 +01:00
evgeny c5a09c1413 Check permission round teardown, blocked error handoff and safe restart callbacks 2026-10-26 14:44:03 +01:00
evgeny 789e5663f7 End unauthorized feedback rounds while preserving watches for member restoration 2026-10-26 14:44:03 +01:00
evgeny 4278eb7851 Wait for incoming transport before late-peer group setup and check restored publishing 2026-10-26 14:44:03 +01:00
evgeny ea1c17593b Test full chat restart and late-peer convergence across member exclusion and restoration 2026-10-26 14:44:03 +01:00
evgeny bf941bfd14 Preserve precise author failure reasons and guard SQLite column allocation 2026-10-26 14:44:03 +01:00
evgeny 4b394b75e0 Cover feedback revocation, purge, delayed cross-channel credentials and transactional faults 2026-10-26 14:44:03 +01:00
evgeny 490b30b956 Update dependent feedback atomically with membership and filter poll results 2026-10-26 14:44:03 +01:00
evgeny 8925503d59 Retain inactive feedback while rebuilding and serving only verified active states 2026-10-26 14:44:03 +01:00
evgeny e7ae4025e2 Expose dataset registration for dependent model startup boundaries 2026-10-26 14:44:03 +01:00
evgeny 42808450b5 Distinguish member author admission, pending credentials and verification errors 2026-10-26 14:44:03 +01:00
evgeny 9c1b8e3e03 Record feedback plan dependency and cross-channel audit gaps 2026-10-26 14:44:03 +01:00
evgeny e1e9d63925 Record excluded-author feedback restart audit findings 2026-10-26 14:44:03 +01:00
evgeny 8e2036b435 Document feedback startup failure for excluded historical authors 2026-10-26 14:44:03 +01:00
evgeny e56790649a Record passing member purge integration and sanitizer validation 2026-10-26 14:44:02 +01:00
evgeny 16c64ca626 Describe Merkle index ownership and mark old sync plan historical 2026-10-26 14:42:59 +01:00
evgeny 26b6eca150 Clarify Merkle pull lifecycle, progress timeout and audit scope 2026-10-26 14:42:59 +01:00
evgeny 81712e74cd Document atomic member purge and verification error contracts 2026-10-26 14:42:59 +01:00
evgeny e4de937953 Use public READY checks in physical member purge regression 2026-10-26 14:42:59 +01:00
evgeny 8b525c06a9 Verify physical purge preserves radio and transport on rollback 2026-10-26 14:42:59 +01:00
evgeny fe182e4acc Check cleanup retries, request ownership and stream rollback 2026-10-26 14:42:59 +01:00
evgeny 87b22966b7 Exercise member cleanup transaction and verification failures 2026-10-26 14:42:59 +01:00
evgeny fbe3e7a279 Make member cleanup atomic and publish removals after commit 2026-10-26 14:42:59 +01:00
evgeny 1f3f1d9a34 Separate missing member verification keys from SQLite failures 2026-10-26 14:42:59 +01:00
evgeny fe7bcb334c Distinguish Ed25519 verification errors from invalid signatures 2026-10-26 14:42:59 +01:00
evgeny f79b9261c7 Record passing stream audit verification and remaining scope 2026-10-26 12:55:48 +01:00
evgeny 6689cf543b Clarify source signing key and interval estimate documentation 2026-10-26 12:54:52 +01:00
evgeny 409d9f3ca9 Record completed stream header audit and align native guide 2026-10-26 12:53:40 +01:00
evgeny de535e1713 Distinguish source mute state from immutable audio codec 2026-10-26 12:47:46 +01:00
evgeny 8533dfc303 Clarify asynchronous publisher and viewer session contracts 2026-10-26 12:45:31 +01:00
evgeny 0f54f5ef66 Specify stream playback clock and audio thread contracts 2026-10-26 12:43:25 +01:00
evgeny c5292c9994 Document stream member admission and wire codec contracts 2026-10-26 12:42:14 +01:00
evgeny 495972cfe6 Clarify stream ring and media cursor ownership and results 2026-10-26 12:40:44 +01:00
evgeny b25acce11b Specify stream queue accounting and timing metric snapshots 2026-10-26 12:33:15 +01:00
evgeny 080b14a51d Document stream flow lifetimes, leases and relay ownership 2026-10-26 12:31:01 +01:00
evgeny 5259c746d1 Record INFO expiry fix and complete IPv6-isolated verification 2026-10-26 12:19:42 +01:00
evgeny b116b20b11 Exercise INFO expiry under real ETCP backpressure 2026-10-26 12:04:31 +01:00
evgeny c148351259 Close expired nine-byte stream INFO requests with overload reason 2026-10-26 12:04:31 +01:00
evgeny 3956711c16 Record expired stream INFO probe defect and isolated evidence 2026-10-26 12:04:31 +01:00
evgeny 840bc9a6b0 Align stream guide with session ownership and current audit status 2026-10-26 12:04:31 +01:00
evgeny 27ed4c74ff Clarify stream session ownership and supplier selection contracts 2026-10-26 12:04:31 +01:00
evgeny 962a2df3f8 Add local channel deletion to desktop channel settings 2026-10-26 10:47:39 +01:00
evgeny d67e0b0c23 Report desktop startup failures and validate generated configs 2026-10-26 10:12:30 +01:00
evgeny 9ab9d01907 Fix Android config storage limits for the strict parser 2026-10-26 10:12:30 +01:00
evgeny 4abebdf35c Record passing stream publisher checks after integration 2026-10-26 09:58:45 +01:00
evgeny ced9dc2340 Merge remote-tracking branch 'origin/master' 2026-10-26 09:50:34 +01:00
evgeny 8627e4f6a5 Record stream packing fix and native regression coverage 2026-10-26 09:50:34 +01:00
evgeny a056b2c262 Describe publisher packing budgets and queued audio rejection 2026-10-26 09:50:34 +01:00
evgeny 017a326a13 Cover stream publisher packing boundaries and actor progress 2026-10-26 09:46:24 +01:00
evgeny 1a9fe0a33b Fix stream publisher audio packing and video progress 2026-10-26 09:44:16 +01:00
evgeny 8e74619501 Make chat joins atomic and test invitation lifecycle failures 2026-10-26 09:19:35 +01:00
evgeny bb6ed1723f Close instance audit with full integration and sanitizer results 2026-10-26 09:09:00 +01:00
evgeny 435ca204fe Clarify that repeated core start preserves the application running flag 2026-10-26 09:08:42 +01:00
evgeny 8640b45e99 Record instance lifecycle fixes, contracts and sanitizer audit evidence 2026-10-26 09:08:42 +01:00
evgeny 4219d5ce1d Specify reload behavior for repeated server sections in public header 2026-10-26 09:08:42 +01:00
evgeny 85e87cc9f8 Read radio hop list through aligned storage 2026-10-26 09:08:42 +01:00
evgeny e577daf6ab Describe conservative reload for duplicate and resolved IPv6 selectors 2026-10-26 09:08:42 +01:00
evgeny 0d6d1aeb19 Restart instances with duplicate server names to preserve all endpoints 2026-10-26 09:08:42 +01:00
evgeny a58f3516ab Clarify first-opened file logger ownership across instances 2026-10-26 09:08:42 +01:00
evgeny 44103038c0 Preserve selected global log path and verify database owner reload 2026-10-26 09:08:42 +01:00
evgeny 06ad255b95 Align instance guide and core lifecycle documentation with audited code 2026-10-26 09:08:42 +01:00
evgeny 9201d8c4f7 Use aligned PCM samples in headless radio integration fixture 2026-10-26 09:08:42 +01:00
evgeny ceaf71caf8 Align headless PCM before passing frames to Opus 2026-10-26 09:08:42 +01:00
evgeny 817e3744ee Reclaim cancelled heap timers before checking async resource counters 2026-10-26 09:08:42 +01:00
evgeny 68ead8c7dc Expose remaining async resource owners in instance regression test 2026-10-26 09:08:42 +01:00
evgeny 59f900810e Check headless clients, timer rollback and external subscription cleanup 2026-10-26 09:08:42 +01:00
evgeny 0d14613244 Document instance ownership, lifecycle, reload and callback contracts 2026-10-26 09:08:42 +01:00
evgeny f5488adab0 Release headless audio contexts, clients and timers on chat stop 2026-10-26 09:08:42 +01:00
evgeny fd93f39c78 Release remaining transport subscriptions at instance destruction 2026-10-26 09:08:42 +01:00
evgeny 1d92591780 Validate headless bindings and honor ephemeral ports in chat startup 2026-10-26 09:08:42 +01:00
evgeny 234c21fb6a Report outstanding allocations before instance teardown assertion 2026-10-26 09:08:42 +01:00
evgeny 88801318bb Include complete ETCP connection type in instance contract test 2026-10-26 09:08:42 +01:00
evgeny 9992228dcb Cover instance callbacks, constructor failures and selective/full reload 2026-10-26 09:08:42 +01:00
evgeny 4e32de8e65 Drain instance-owned sockets and registries without saved callback neighbors 2026-10-26 09:08:42 +01:00
evgeny a7d2333deb Reload complete endpoint settings and restart changed resource owners 2026-10-26 09:08:42 +01:00
evgeny 5e63bc2a42 Share atomic network index construction and typed socket teardown 2026-10-26 09:08:42 +01:00
evgeny b44ea19b4b Close config parser audit after the full integration suite 2026-10-26 09:08:42 +01:00
evgeny d681d5abf0 Record parser boundary, rollback and sanitizer audit evidence 2026-10-26 09:08:24 +01:00
evgeny 7ea1fa9954 Validate instance construction and retain the global log path safely 2026-10-26 09:08:24 +01:00
evgeny 372b7d7f65 Retain removed instance callbacks until nested dispatch completes 2026-10-26 09:08:24 +01:00
evgeny e5e61723d8 Inject config read faults through fortified fread as well 2026-10-26 09:08:24 +01:00
evgeny 7fe77a49c9 Restore console diagnostics after parser dump assertions 2026-10-26 09:08:24 +01:00
evgeny 9888820146 Describe parser validation, list order and service defaults 2026-10-26 09:08:23 +01:00
evgeny 9a7091b595 Document strict parser ownership and validate provided peer keys 2026-10-26 09:08:23 +01:00
evgeny 1041849030 Reject oversized service strings and cover scalar bounds 2026-10-26 09:08:23 +01:00
evgeny eff0446f8d Align boolean settings and timer bounds across parser and updater 2026-10-26 09:08:23 +01:00
evgeny e4852c82b4 Check service scalars and proxy ports before storing configuration 2026-10-26 09:08:23 +01:00
evgeny 99d52afd3f Validate global scalar options before narrowing or timer conversion 2026-10-26 09:08:23 +01:00
evgeny 4abeafa20e Normalize malformed key duplicates before strict config verification 2026-10-26 09:08:23 +01:00
evgeny 70b7823993 Use debug and socket test APIs with their declared contracts 2026-10-26 09:08:23 +01:00
evgeny 46bf5b8541 Test parser rejection, CIDR boundaries and allocation rollback 2026-10-26 09:08:23 +01:00
evgeny d21af324ac Validate network keys before use and keep secret keys out of dumps 2026-10-26 09:08:23 +01:00
evgeny f581fa423b Reject configuration when an option handler or allocation fails 2026-10-26 09:08:23 +01:00
evgeny bff354f9cc Validate complete protocol versions, network keys and endpoint ports 2026-10-26 09:08:23 +01:00
evgeny 7593120bd9 Parse CIDR, control endpoints and storage sizes without truncation 2026-10-26 09:08:23 +01:00
evgeny 869421cc05 Audit LAN docs and enforce stream member exclusions
Document LAN transport contracts and the completed part of the stream audit. Reject owner-deleted members before profile verification and add network lifecycle coverage for source, supplier and local member removal.

Validation: seven stream checks and all 195 core tests pass; proxy 9/9, burst and load 8/8 pass.
2026-10-26 08:55:31 +01:00
evgeny 6bd4690c3b Date transport audit completion after final sanitizer checks 2026-10-26 00:01:10 +01:00
evgeny 018f8a20f3 Close transport header audit and record integration validation 2026-10-26 00:00:11 +01:00
evgeny 13f379621a Keep route ACK fault tests effective with fortified libc calls 2026-10-25 23:57:53 +01:00
evgeny 8bacf73e86 Intercept fortified recvfrom in socket monitor fault tests 2026-10-25 23:56:40 +01:00
evgeny f327f7f434 Describe REALITY codec, protected stream and relay lifecycle 2026-10-25 23:53:34 +01:00
evgeny 5e7eb6290f Test STUN recheck with an existing and a newly discovered path 2026-10-25 23:52:41 +01:00
evgeny bdf0bdf873 Close REALITY relay cleanly when event monitoring fails 2026-10-25 23:52:41 +01:00
evgeny 2f4830a3d0 Recheck each STUN path once and clarify result validity 2026-10-25 23:51:47 +01:00
evgeny f37ab0824d Complete REALITY relay half-close on socket hangup 2026-10-25 23:49:47 +01:00
evgeny 7e526521eb Document REALITY session ownership and test relay failure cleanup 2026-10-25 23:48:38 +01:00
evgeny 88b05c07d9 Harden REALITY record lifetime, relay cleanup and input contracts 2026-10-25 23:40:56 +01:00
evgeny 47bf724748 Include errno in call ring I/O fault test 2026-10-25 23:37:09 +01:00
evgeny 2949101ff8 Test per-thread call traces, counter wrap and dump I/O errors 2026-10-25 23:30:56 +01:00
evgeny c0365ebb38 Keep teardown traces per thread and retain history across wrap 2026-10-25 23:29:45 +01:00
evgeny 9a13989c7e Document SOCKS ownership and cover empty UDP and input limits 2026-10-25 23:26:24 +01:00
evgeny 36900780f2 Preserve SOCKS stream data and make control startup cancellable 2026-10-25 23:25:16 +01:00
evgeny 6660f59b3f Fix automatic endpoint ownership, retries and scan teardown 2026-10-25 23:16:17 +01:00
evgeny f8c299c2e3 Test socket monitor address loss, callbacks and init faults 2026-10-25 22:58:54 +01:00
evgeny 9296b36366 Make socket monitoring bounded and cancel pending notifications 2026-10-25 22:56:45 +01:00
evgeny fe6b79127f Record passing packet dump sanitizer validation 2026-10-25 22:46:21 +01:00
evgeny dd81f7a665 Record packet dump fix and FreeBSD socket monitor finding 2026-10-25 22:44:55 +01:00
evgeny ce30ec5fe6 Align packet dump and CRC32 contracts with implementations 2026-10-25 22:43:43 +01:00
evgeny c3fa6d4db1 Exercise packet dump limits, protocols and fragment output 2026-10-25 22:32:22 +01:00
evgeny 235c2c4f4d Bound IPv4 packet dump reads and handle fragments 2026-10-25 22:32:22 +01:00
evgeny 9fb939ff24 Document unsafe packet dump reads found during audit 2026-10-25 22:32:22 +01:00
evgeny e035f53ab6 Fix stale socket references in connectivity probes 2026-10-25 22:30:52 +01:00
evgeny 8b0002e489 Disable UTUN by default in chat frontends and retain core bootstrap transports 2026-10-25 22:10:06 +01:00
evgeny fcc4a2cf42 Ignore zero-port addresses in connection manager candidates 2026-10-25 21:01:03 +01:00
evgeny 539f09004c Use channel member snapshots for desktop participant details 2026-10-25 20:04:59 +01:00
evgeny c832a5d7a5 Unify member snapshots and fix Android member status flicker 2026-10-25 19:29:44 +01:00
evgeny f09eb81381 Fix NAT stress test time helper on Windows 2026-10-25 18:24:07 +01:00
evgeny 59b3b9bd34 Check remote and local member-file ACL refusals separately 2026-10-25 18:10:58 +01:00
evgeny b3d3df5c57 Exercise signed LAN endpoints over isolated IPv6 interfaces 2026-10-25 18:06:46 +01:00
evgeny e75bd460b8 Avoid identity reload when removing expired LAN candidates 2026-10-25 18:00:56 +01:00
evgeny 77b43363fb Run signed LAN integration separately from other network tests 2026-10-25 18:00:01 +01:00
evgeny 199839b273 Cover socket reuse and TCP LAN recovery and document lifecycle 2026-10-25 17:58:18 +01:00
evgeny 8dd28fb90a Distinguish LAN nonce failures from ordinary unknown devices 2026-10-25 17:55:35 +01:00
evgeny 94a76e569e Respect SOCKS policy and report LAN lookup failures precisely 2026-10-25 17:55:34 +01:00
evgeny 09c7e0c937 Test signed LAN discovery, replay rejection and NCD recovery 2026-10-25 17:52:08 +01:00
evgeny 469f95c596 Apply nonce-verified LAN endpoints to offline NCD transports 2026-10-25 17:47:08 +01:00
evgeny 88c2d7a4e3 Share LAN interface matching for socket announcements and NCD 2026-10-25 17:44:52 +01:00
evgeny e8713e7a2c Load known node identities for verified LAN candidates 2026-10-25 17:43:21 +01:00
evgeny 28c447370a Add signed LAN endpoint announcements and nonce proofs 2026-10-25 17:42:40 +01:00
evgeny f276fda411 Restore Android core activity after internal restart 2026-10-25 17:20:42 +01:00
evgeny c26b626c35 Handle comments consistently in desktop socket protocol settings 2026-10-25 16:35:54 +01:00
evgeny 7bcdccc4d6 Verify autosocket protocol modes across IPv4 and IPv6 lifecycle 2026-10-25 16:35:54 +01:00
evgeny fc8a06547d Test automatic socket protocol configuration and Android port reuse 2026-10-25 16:35:54 +01:00
evgeny b1a07df606 Translate automatic socket protocol settings 2026-10-25 16:35:54 +01:00
evgeny 9d465bce16 Add Android autosocket protocol selection to network settings 2026-10-25 16:35:54 +01:00
evgeny eda65ece52 Generate Android autosockets per selected protocol and retain ports 2026-10-25 16:35:54 +01:00
evgeny ae85423e39 Add automatic socket protocol selector to desktop settings 2026-10-25 16:35:54 +01:00
evgeny f3bc5acacc Persist automatic socket protocols in desktop configuration 2026-10-25 16:35:54 +01:00
evgeny 556f6e0b9e Add selectable protocols for automatic transport sockets 2026-10-25 16:35:54 +01:00
evgeny 270b9fcf80 Merge remote-tracking branch 'origin/master' 2026-10-25 16:30:55 +01:00
evgeny 288b8091ce Document targeted recovery and retain scheduler diagnostics 2026-10-25 16:26:14 +01:00
evgeny 46f6c03147 Keep requests queued by callbacks for the next scheduler batch 2026-10-25 16:19:40 +01:00
evgeny 87dd27d022 Test targeted chat synchronization across peer events and service lifecycle 2026-10-25 16:13:53 +01:00
evgeny 2eade0a7c0 Scope deferred chat synchronization to channel and peer 2026-10-25 16:11:11 +01:00
evgeny 0e17756e19 Show stream playback buffer chains on desktop and Android
Send coalesced per-hop telemetry every 200 ms ahead of video DATA using the shared ETCP transport. Measure pending frames before ETCP handoff, retain stale and unavailable node values, and display the worst path with playback tempo.

Bump stream wire protocol to v7. Validate with 187 core tests, 21 desktop player tests, two Android indicator tests, and an Android APK build.
2026-10-25 15:21:23 +01:00
evgeny 5b5221189c Buffer stream PCM before playback and recover underruns without resets 2026-10-25 12:51:19 +01:00
evgeny 677f79881c Diagnose stream audio underruns and fixture timing jitter 2026-10-25 12:30:30 +01:00
evgeny 3ffacbfe37 Document stream recovery validation and existing Qt audio flake 2026-10-25 12:06:35 +01:00
evgeny c3cf86b9e0 Recover streams after five seconds and start from complete keys
Preserve queued media under backpressure, advertise retained keyframe ranges in stream wire v6, and reopen stalled subflows without resetting playback.

Cover large fragmented keys, sustained slow delivery, missing subflows, buffer eviction and stale bootstrap snapshots in integration regressions.
2026-10-25 12:03:49 +01:00
evgeny 4a785c2598 Improve stream recovery, delivery diagnostics and buffer indicators
Preserve essential FEC parts under pressure, coordinate stale-data gaps and reopen source subflows in parallel after transport failures.

Add per-peer network and playback diagnostics, Android and desktop buffer indicators, and regression coverage for Wi-Fi switching and congestion.
2026-10-25 01:18:02 +02:00
evgeny b7d74d8f87 Verify every NCD control ID byte and clarify new-socket scope 2026-10-24 20:27:57 +02:00
evgeny db0d7a1f47 Document NCD startup rollback reentrant lifetime and address snapshots 2026-10-24 20:24:22 +02:00
evgeny 9844fdefcb Align automatic socket documentation with shared NCD link matching 2026-10-24 20:24:22 +02:00
evgeny a353797edb Specify NCD ownership callbacks matching and fixed little-endian control wire 2026-10-24 20:22:45 +02:00
evgeny b83a28becc Keep NAT remeasurement fixture isolated from new direct helper links 2026-10-24 20:20:09 +02:00
evgeny a3f004772a Align ETCP fixtures with NCD identity and failed-open contracts 2026-10-24 20:20:09 +02:00
evgeny 702389d8d9 Retain NCD entry and transport through synchronous CLOSE callbacks 2026-10-24 20:18:15 +02:00
evgeny 88004f11ca Trigger NCD CLOSE on an empty unsuspended queue 2026-10-24 20:17:13 +02:00
evgeny 1f6f815917 Reproduce NCD teardown during synchronous CLOSE queue notification 2026-10-24 20:15:30 +02:00
evgeny 2a7266e17f Check IPv6 scope on the matching NCD link 2026-10-24 20:15:30 +02:00
evgeny e137778ba2 Exercise IPv6 REALITY guards and reentrant node snapshot replacement 2026-10-24 20:15:30 +02:00
evgeny 496a3c788e Cover NCD candidate policy constructor cancellation and nested removal 2026-10-24 20:15:30 +02:00
evgeny 772c0728e1 Use one NCD address matcher for opens updates and new sockets 2026-10-24 20:15:30 +02:00
evgeny b23d5e6047 Unify NCD opens and retain owners across failed startup and callbacks 2026-10-24 20:15:30 +02:00
evgeny 4695fe4371 Register NCD transport events atomically and reuse ETCP close lifecycle 2026-10-24 20:15:30 +02:00
evgeny 28c951ed9e Reject stale NCD notifications and validate complete control frames 2026-10-24 20:15:30 +02:00
evgeny 2cc5a6df91 Reproduce NCD startup failures stale events and malformed control 2026-10-24 20:15:30 +02:00
evgeny 10d6ddee38 Wait for target discovery before member file network transfers 2026-10-24 20:15:30 +02:00
evgeny 4314dff390 Expose CM and topology failures in member file network diagnostics 2026-10-24 20:14:58 +02:00
evgeny c311bb7a1f Prevent deferred CM readiness from restarting cancelled file transfers 2026-10-24 20:14:58 +02:00
evgeny b387c4b127 Preserve unowned member download temporaries on refusal and cancellation 2026-10-24 20:14:29 +02:00
evgeny 6d6afb4faa Align FULL and inline loss counters in dummynet documentation 2026-10-24 19:57:24 +02:00
evgeny e996e09f6e Specify dummynet datagram timing reconfiguration and filter ownership contracts 2026-10-24 19:57:24 +02:00
evgeny 8d035a065a Cover partial dummynet startup rollback without resource leaks 2026-10-24 19:57:24 +02:00
evgeny 0df339c384 Verify inline filters with real UDP delivery and independent ETCP teardown 2026-10-24 19:57:24 +02:00
evgeny c341a9b6cc Record passing full validation after ETCP diagnostics merge 2026-10-24 19:45:37 +02:00
evgeny 897cc007e1 Merge current master and reconcile completed member-files fixes 2026-10-24 19:38:40 +02:00
evgeny 6c9be8b134 Record full-suite failure deleting an unowned member-files temp 2026-10-24 19:26:27 +02:00
evgeny cfa0419576 Record repeated slow-duplex failures with native and real clocks 2026-10-24 19:09:34 +02:00
evgeny f8a2ecaabd Add isolated slow-duplex measurements and record BBR diagnosis 2026-10-24 19:07:18 +02:00
evgeny 79e37f64f8 Document member files audit findings and verified fixes 2026-10-24 18:47:06 +02:00
evgeny 4d729a2ff0 docs(member-files): align lifecycle and receipt retry behavior 2026-10-24 18:47:06 +02:00
evgeny 4f96926f6b docs(member-files): complete public request and transfer contracts 2026-10-24 18:47:06 +02:00
evgeny c1da55ad87 docs(member-files): clarify storage lifecycle and internal owners 2026-10-24 18:47:06 +02:00
evgeny f7b064a11a docs(member-files): specify wire codec and worker ownership 2026-10-24 18:47:06 +02:00
evgeny 41f0aa2439 fix(member-files): reject local FIFO without blocking disk worker 2026-10-24 18:47:06 +02:00
evgeny 1c1b2b2026 test(member-files): detect blocking open of local FIFO sources 2026-10-24 18:47:06 +02:00
evgeny 488577ac0e test(member-files): verify timed replay and bulk removal 2026-10-24 18:47:06 +02:00
evgeny 4d40b6f5f7 fix(member-files): bound busy retries by receipt lifetime 2026-10-24 18:47:06 +02:00
evgeny 2d8384830d test(member-files): cover bulk mutations and lost result replay 2026-10-24 18:47:06 +02:00
evgeny 0c8e9eef3c fix(member-files): retry busy mutations within replay guarantees 2026-10-24 18:47:06 +02:00
evgeny 20b4975d57 fix(member-files): prevent restart after early transfer cancellation 2026-10-24 18:47:06 +02:00
evgeny 0f42f92feb fix(member-files): clean up only owned download temporaries 2026-10-24 18:47:06 +02:00
evgeny 0b2dac3c5b test(member-files): retain route precondition after ABI diagnosis 2026-10-24 18:47:06 +02:00
evgeny 5df6d0c8f3 test(member-files): log startup state before transfer 2026-10-24 18:47:06 +02:00
evgeny a198cfb9e3 Bind inline dummynet filters to UDP link lifetime and report failures 2026-10-24 17:33:59 +02:00
evgeny 83bf76dd41 Release borrowed send-hook owners before ETCP link teardown 2026-10-24 17:33:59 +02:00
evgeny 36c096c4e9 Make UDP dummynet configuration and resource failures recoverable 2026-10-24 17:33:59 +02:00
evgeny 29d54ed20d Reproduce dummynet configuration datagram and timer failures 2026-10-24 17:33:59 +02:00
evgeny e59ef240e8 test(member-files): let transfer own initial route request 2026-10-24 17:33:47 +02:00
evgeny 27dd9e7b60 test(member-files): preserve unowned download temp on refusal 2026-10-24 17:33:47 +02:00
evgeny 8185b83eba Record final RTT timer, callback and network validation 2026-10-24 17:26:59 +02:00
evgeny 76afc56be8 Make RTT callback regression independent of host uptime 2026-10-24 17:26:59 +02:00
evgeny 5420a07ffc Refresh RTO before RTT callbacks can close the link 2026-10-24 17:26:59 +02:00
evgeny f00d67ca3c Trace refreshed RTO deadlines without per-packet debug noise 2026-10-24 17:26:59 +02:00
evgeny 90dff0b2f2 Refresh pending retransmit timer when timestamp RTT changes 2026-10-24 17:26:59 +02:00
evgeny 83734c920d Expose existing RTO timer refresh and regress timestamp shrink 2026-10-24 17:26:59 +02:00
evgeny e1dcee3c86 Record verified RTT filter and RTO recovery fixes 2026-10-24 17:26:59 +02:00
evgeny d5114f36b4 Clarify timestamp RTT role in transport contracts 2026-10-24 17:26:59 +02:00
evgeny 68a225baec Exercise RTT changes through real ETCP and document RTO inputs 2026-10-24 17:26:59 +02:00
evgeny ef404da44c Recover DATA RTT sampling after path delay increases 2026-10-24 17:26:59 +02:00
evgeny dbda8a24d7 Verify RTT hold rounds and document filter timing 2026-10-24 17:26:59 +02:00
evgeny bb462bad69 Preserve BBR RTT filter age and full-width probe deadlines 2026-10-24 17:26:59 +02:00
evgeny deee734e6c Record duplex validation and remaining BBR follow-ups 2026-10-24 17:26:59 +02:00
evgeny 8ff4a0bf46 Document ETCP receiver-clock bandwidth sampling 2026-10-24 17:26:59 +02:00
evgeny d2703b2145 Use receiver delivery clock for ETCP bandwidth samples 2026-10-24 17:26:59 +02:00
evgeny 9b72a0dadf Close media contract audit and record architecture review 2026-10-24 17:26:12 +02:00
evgeny 5e3701bb2f Clarify encrypted attachment MIME and UI contracts 2026-10-24 17:26:12 +02:00
evgeny 4bab1f7ea4 Align media delivery architecture docs with implementation 2026-10-24 17:26:12 +02:00
evgeny 9d9c82fb03 Document validated MIME fix and regression results 2026-10-24 17:26:12 +02:00
evgeny 99c1ee3394 test(media): cover encrypted MIME validation and side effect free rejection 2026-10-24 17:26:11 +02:00
evgeny d88e39fb4e chat: reject unsupported encrypted attachment types before side effects 2026-10-24 17:26:11 +02:00
evgeny f63d640c95 media: share bounded content type validation in encrypted containers 2026-10-24 17:26:11 +02:00
evgeny 86b7f9cf44 docs(media): record accepted but unreadable MIME containers 2026-10-24 17:26:11 +02:00
evgeny f331d177ca docs(media): clarify preparation ownership and active protocol commands 2026-10-24 17:26:11 +02:00
evgeny 28bbd62d74 docs(media): specify attachment metadata and voice file contracts 2026-10-24 17:26:11 +02:00
evgeny c1717d4047 docs(media): record validated SQLite announcement fix 2026-10-24 17:26:11 +02:00
evgeny 4bfdb1dcc2 test(media): restore console after SQL diagnostic assertions 2026-10-24 17:26:11 +02:00
evgeny 6e3be1aaf3 test(media): verify exact announcement identities after SQL recovery 2026-10-24 17:26:11 +02:00
evgeny eea2b22c4e test(media): cover malformed local announcements and SQLite failures 2026-10-24 17:26:11 +02:00
evgeny 81fc4291db media: validate SQLite records before local block announcements 2026-10-24 17:26:11 +02:00
evgeny 1a212489fd docs(media): correct announcement function reference 2026-10-24 17:26:11 +02:00
evgeny 0d616ce1e7 docs(media): record unchecked SQLite announcements and fix plan 2026-10-24 17:26:11 +02:00
evgeny 7ff8e1f15a docs(media): specify crypto and file transfer ownership contracts 2026-10-24 17:26:11 +02:00
evgeny 40e2fe2e27 docs(media): record validated voice duration fix 2026-10-24 17:26:11 +02:00
evgeny 359a9f3dfc test(media): cover voice duration bounds and early rejection 2026-10-24 17:26:11 +02:00
evgeny 68a7695d81 media: reject voice duration by complete frames before encoding 2026-10-24 17:26:11 +02:00
evgeny 6f3d634c77 media: share attachment duration limit 2026-10-24 17:26:11 +02:00
evgeny 4177ab3536 docs(media): record voice duration boundary defect and fix plan 2026-10-24 17:26:11 +02:00
evgeny 80558f6686 Merge remote-tracking branch 'origin/master' 2026-10-24 17:15:42 +02:00
evgeny da5cf6fc99 Prepare signed existing members before end-to-end CHAT joining 2026-10-24 17:00:53 +02:00
evgeny e6e866a41a Seed complete members in isolated database sync fixtures 2026-10-24 17:00:53 +02:00
evgeny e1675f6910 Preserve chat stress failure logs and group admission diagnostics 2026-10-24 16:56:52 +02:00
evgeny bb13824ad8 Complete NAT wire lifecycle scheduling and diagnostic contracts 2026-10-24 16:53:10 +02:00
evgeny 857a4cee2f Exercise NAT startup rollback and UDP timeout allocation failure 2026-10-24 16:52:10 +02:00
evgeny a6444725da Reject UDP probes when their timeout cannot be scheduled 2026-10-24 16:51:34 +02:00
evgeny 4a00da31da Document complete membership queries separately from row presence 2026-10-24 16:50:41 +02:00
evgeny af50fde9d9 Verify CHAT admission excludes placeholders and deleted members 2026-10-24 16:50:41 +02:00
evgeny f1b62f9112 Require active complete membership for CHAT group admission 2026-10-24 16:46:01 +02:00
evgeny 0b4997c5d5 Release removed NAT helper sockets and reject partial startup 2026-10-24 16:40:51 +02:00
evgeny b8dd2b8cc5 Verify media cancellation without reading a closed CM handle 2026-10-24 16:31:49 +02:00
evgeny 6cfd88afcf Reject zero CM request ids before creating peer state 2026-10-24 16:25:27 +02:00
evgeny 8e7fb1f31b Reconcile CM protocol scheduling cache and cleanup contracts 2026-10-24 16:24:30 +02:00
evgeny 00a85a1468 Keep local CM demand after stale control and reject zero requests 2026-10-24 16:22:15 +02:00
evgeny 182fb97970 Remove obsolete CM disconnect and clarify service ownership 2026-10-24 16:22:15 +02:00
evgeny e6a812042f Check CM bootstrap ownership and mandatory monitor timers 2026-10-24 16:17:20 +02:00
evgeny 2f3cf0933c Keep READY intermediaries eligible and test CM allocation failures 2026-10-24 16:14:48 +02:00
evgeny 80451c43be Make CM cleanup allocation-free and reject incomplete startup 2026-10-24 16:09:39 +02:00
evgeny 007f7c8ae8 Preserve group attachment before transport readiness 2026-10-24 16:01:29 +02:00
evgeny f541ab428b Describe BGP commit boundaries and diagnose initialization failures 2026-10-24 15:57:40 +02:00
evgeny 7ebfddfc4b Clarify group processing callbacks and failed route installation 2026-10-24 15:56:36 +02:00
evgeny 56d513ed85 Inject topology pool database registry and radio timer failures 2026-10-24 15:52:39 +02:00
evgeny d1562bdd0e Check that late BGP allocation failure preserves accepted state 2026-10-24 15:51:43 +02:00
evgeny 145dd1e5ab Prepare BGP paths before committing received node state 2026-10-24 15:50:17 +02:00
evgeny ab5c077600 Unwind topology initialization on pool and SQLite failures 2026-10-24 15:49:42 +02:00
evgeny 6b413d67a6 Exercise group creation rollback radio retry and BGP subnets 2026-10-24 15:48:58 +02:00
evgeny 4363a424d0 Reject incomplete groups and refresh BGP subnet ownership 2026-10-24 15:47:28 +02:00
evgeny 086eefed55 Keep both test transports owned while checking invite timeout 2026-10-24 15:41:16 +02:00
evgeny 5e8ff95c99 Verify invite deadlines and transport loss with shared owners 2026-10-24 15:38:42 +02:00
evgeny 21d8b3844e Apply refreshed peer priorities without replacing group requests 2026-10-24 15:36:12 +02:00
evgeny a7ffaf497e Include concrete transport state in invite regression tests 2026-10-24 15:30:37 +02:00
evgeny 9ce0abe5a9 Cover invite response bounds isolation and failure propagation 2026-10-24 15:30:04 +02:00
evgeny 483e89cd79 Validate channel descriptions and isolate invite request ownership 2026-10-24 15:28:44 +02:00
evgeny 4d9e624f8e Reconcile router protocol and architecture with implementation 2026-10-24 15:15:35 +02:00
evgeny bafda5ae3a Merge origin/master with encrypted attachment ownership fixes
Validation: ./build.sh --no-gui -j4 and make check -j4 passed; 186 tests, no failures.
2026-10-24 15:11:50 +02:00
evgeny 09e620e12a Specify router local delivery, callbacks, flow control and reset contracts 2026-10-24 15:10:06 +02:00
evgeny 3bd9b964fa Remove obsolete router state and clarify receive diagnostics 2026-10-24 15:07:41 +02:00
evgeny a258b77240 Cancel pending transit queues when destroying the router 2026-10-24 15:06:48 +02:00
evgeny 936bacbe4b Clarify encrypted output cleanup contract on filesystem errors 2026-10-24 15:00:05 +02:00
evgeny 1227027c2f Record validated encrypted attachment ownership fix and remaining audit scope 2026-10-24 14:59:12 +02:00
evgeny d8089f8d12 Release router unit fixture registry ownership completely 2026-10-24 14:56:23 +02:00
evgeny 4862a52684 Document encrypted attachment preparation publication and recovery ownership 2026-10-24 14:55:24 +02:00
evgeny e40d8de1b2 Keep full router jitter precision in monitor snapshots 2026-10-24 14:54:48 +02:00
evgeny dbf6bb759c Preserve the unsigned range of router RTT jitter 2026-10-24 14:54:48 +02:00
evgeny be0bd224fa Use canonical media base throughout attachment recovery 2026-10-24 14:51:32 +02:00
evgeny 6bf6d99b9c Test service cancellation after encrypted attachment rename 2026-10-24 14:50:32 +02:00
evgeny 7caebc5a11 Verify attachment recovery preserves active temp owners across restarts 2026-10-24 14:48:25 +02:00
evgeny 6c13755a5c Reject invalid local router payloads and report delivery failures 2026-10-24 14:48:04 +02:00
evgeny c6f28571b7 Keep local callback context private and fully detach services 2026-10-24 14:46:33 +02:00
evgeny 76ba7aae6a Cover encrypted file aliases and I/O failures through publication 2026-10-24 14:45:32 +02:00
evgeny 066b895055 Remove closing router channels before notifying services 2026-10-24 14:44:22 +02:00
evgeny a297d2d649 Record validated ACK batching and remaining solo duplex limits 2026-10-24 14:43:03 +02:00
evgeny f09d76e3fd Recover owned encrypted attachment temporaries in both storage trees 2026-10-24 14:43:03 +02:00
evgeny 7737391ded Document absolute ACK scheduling and cross-path precedence 2026-10-24 14:43:03 +02:00
evgeny dc08256025 Clarify due ACK precedence and bounded burst behavior 2026-10-24 14:43:03 +02:00
evgeny 72d7405a97 Serve due path ACKs before DATA on another link 2026-10-24 14:43:03 +02:00
evgeny 73096e8e3e Verify ACK deadlines through link down and removal 2026-10-24 14:43:03 +02:00
evgeny 51c667edd8 Distinguish early ACK packets from legitimate batched entries 2026-10-24 14:43:03 +02:00
evgeny 2edf09fde1 Cover ACK batching deadlines, timer races, and failure cleanup 2026-10-24 14:43:03 +02:00
evgeny 6ab2526966 Align ACK contracts and diagnostics with deadline state 2026-10-24 14:43:03 +02:00
evgeny c1b0772071 Honor absolute ACK deadlines across wakes and piggyback 2026-10-24 14:43:03 +02:00
evgeny 159237a70c Define absolute ACK deadlines and urgent fallback contracts 2026-10-24 14:43:03 +02:00
evgeny c8051619c1 Reproduce premature ACKs before their absolute deadline 2026-10-24 14:43:03 +02:00
evgeny 2b74d2bf4f Record final queue diagnostics validation and observations 2026-10-24 14:43:03 +02:00
evgeny 35bd19b6c0 Observe ACK queue peaks before immediate send 2026-10-24 14:43:03 +02:00
evgeny 7e166c650c Document multipath diagnostics and the ACK deadline defect 2026-10-24 14:43:03 +02:00
evgeny 055ffa27b2 Add offline multipath charts and count timestamped ACKs 2026-10-24 14:43:03 +02:00
evgeny cd3cf38f06 Expose callback and stream progress in multipath snapshots 2026-10-24 14:43:03 +02:00
evgeny 12b0ab437e Capture buffered multipath queue and pacing diagnostics 2026-10-24 14:43:03 +02:00
evgeny a9bbb470c2 Record full validation of retry scheduling changes 2026-10-24 14:43:03 +02:00
evgeny 6894c66f3a Record passing fault matrix and remaining duplex limits 2026-10-24 14:43:03 +02:00
evgeny a2f9b76d10 Record retry scheduler architecture and regression coverage 2026-10-24 14:43:03 +02:00
evgeny 3d40951e66 Clarify input resumption with queued DATA 2026-10-24 14:43:03 +02:00
evgeny 4350b54769 Publish attachment output once and preserve ownership through cancellation 2026-10-24 14:41:39 +02:00
evgeny 92d52d25a8 Prepare encrypted attachments in exclusively owned durable temporaries 2026-10-24 14:40:53 +02:00
evgeny 9e0949434e Preserve video temp mode and test durable file commit boundaries 2026-10-24 14:39:46 +02:00
evgeny aa7a9b74f4 Select ordinary temporary file mode for copies and media blocks 2026-10-24 14:38:54 +02:00
evgeny 12556344b0 Add durable owned temporary file lifecycle and shared publication helpers 2026-10-24 14:38:34 +02:00
evgeny 2e3ab00ce6 Design owned temporary output and durable publication for encrypted attachments 2026-10-24 14:34:00 +02:00
evgeny f92c78a2e0 Merge remote-tracking branch 'origin/master' 2026-10-24 14:33:18 +02:00
evgeny 7c7c316c3f Document atomic local publication and bootstrap cleanup 2026-10-24 14:25:18 +02:00
evgeny 94aaf3c8e3 Align topology model documentation with current runtime contracts 2026-10-24 14:23:50 +02:00
evgeny c282d03f25 Describe NODEINFO byte layout, identity and registry semantics 2026-10-24 14:20:29 +02:00
evgeny f7db49fc97 Cover local topology replacement allocation failures 2026-10-24 14:18:42 +02:00
evgeny 8cc97d2ffe Record reproducible encrypted file alias data loss during media audit 2026-10-24 14:17:35 +02:00
evgeny f9994e11b5 Clarify local update ownership, results and failure contracts 2026-10-24 14:17:13 +02:00
evgeny 1e0281d4d8 Prepare local topology replacements before retiring old state 2026-10-24 14:16:39 +02:00
evgeny 42a58881ca Document SQLite snapshots, projections and membership contracts 2026-10-24 14:13:26 +02:00
evgeny 19c3cc0434 Reject interrupted membership channel queries 2026-10-24 14:10:28 +02:00
evgeny 81e2a9aa4a Return peer lists atomically after successful SQL iteration 2026-10-24 14:09:36 +02:00
evgeny 575a3788e3 Roll back failed channel deletion and node classification 2026-10-24 14:07:28 +02:00
evgeny 461417beac Record completed proxy fixes and architecture validation results 2026-10-24 14:03:56 +02:00
evgeny 26b5da6835 Release partial SQL bootstrap records on allocation failures 2026-10-24 14:03:48 +02:00
evgeny 99608de811 Reject failed topology writes and malformed stored signatures 2026-10-24 14:01:37 +02:00
evgeny 5c4207c145 Keep resolved routing audit details out of the task backlog 2026-10-24 14:00:22 +02:00
evgeny a42dc38874 Check real raw ICMP explicitly alongside deterministic loopback 2026-10-24 14:00:17 +02:00
evgeny 83194b19c7 Use supported TCP proxy exit option in TUN integration fixture 2026-10-24 13:59:29 +02:00
evgeny 14c5ddf864 Propagate failures when storing verified node identities 2026-10-24 13:57:05 +02:00
evgeny f10a6f70c5 Describe checked datagram startup and bounded TCP HUP handling 2026-10-24 13:54:40 +02:00
evgeny e2ee5f2397 Document atomic proxy client creation and instance shutdown order 2026-10-24 13:52:22 +02:00
evgeny 324b289968 Bound topology dump writes and return the actual length 2026-10-24 13:45:08 +02:00
evgeny 5914e26579 Update datagram and TCP exit documentation for explicit ownership 2026-10-24 13:42:20 +02:00
evgeny 2894e06014 Document HUP polling contract and isolate ICMP fault injection 2026-10-24 13:41:16 +02:00
evgeny d0edacb7b9 Test HUP registration failure and teardown with pending TCP writes 2026-10-24 13:39:50 +02:00
evgeny 1ce285c09b Preserve datagram bindings and verify optional ICMP behavior 2026-10-24 13:38:45 +02:00
evgeny 8dcd2fac3b Record topology dump truncation defect found during audit 2026-10-24 13:37:22 +02:00
evgeny bb2ef05157 Roll back required TUN mappings and verify instance startup failures 2026-10-24 13:36:22 +02:00
evgeny c4eddfe50e Cover proxy startup rollback and datagram socket failures 2026-10-24 13:34:51 +02:00
evgeny f0629ea679 Exercise orderly and abrupt TLS shutdown in proxy integration 2026-10-24 13:29:45 +02:00
evgeny 4da9d85545 Honor TCP read backpressure across HUP and restore polling 2026-10-24 13:28:44 +02:00
evgeny d5444fb9bc Check UDP socket operations and roll back incomplete flows 2026-10-24 13:25:43 +02:00
evgeny 50da7fe457 Make TCP proxy construction atomic and retain instance datagrams 2026-10-24 13:24:30 +02:00
evgeny 99be040488 Separate ICMP exit startup from shared context ownership 2026-10-24 13:23:58 +02:00
evgeny 902ffa05b4 Record NODEINFO parsing fix and sanitizer validation 2026-10-24 13:21:42 +02:00
evgeny 051b13e161 docs(proxy): align planned teardown with instance ownership 2026-10-24 13:18:52 +02:00
evgeny 04ace670ed docs(proxy): design error handling and lifecycle fixes 2026-10-24 13:17:33 +02:00
evgeny 99dd48480f Align REALITY round-trip fixture with NODEINFO ownership 2026-10-24 13:09:16 +02:00
evgeny acd9dcd1a8 Cover empty NODEINFO outputs and malformed BGP preservation 2026-10-24 13:03:42 +02:00
evgeny 790978458c Make NODEINFO section parsing independent of requested outputs 2026-10-24 13:01:30 +02:00
evgeny f9a3830416 Add NODEINFO wire parsing and allocation regressions 2026-10-24 12:59:00 +02:00
evgeny 5f51149622 Record routing audit progress and NODEINFO parsing defect 2026-10-24 12:42:47 +02:00
evgeny 0688ffc26d docs(proxy): qualify integration audit results 2026-10-24 12:39:54 +02:00
evgeny ec1fc52da1 docs(proxy): record teardown findings and refine counters 2026-10-24 12:39:09 +02:00
evgeny 5e80a9cc6c docs(proxy): consolidate current protocol and audit coverage 2026-10-24 12:38:27 +02:00
evgeny f003aaa92d docs(proxy): reconcile TCP client server and listener behavior 2026-10-24 12:36:16 +02:00
evgeny bf03348c64 Correct connectivity probe and IPv4 routing documentation 2026-10-24 12:19:22 +02:00
evgeny 0445c38c31 Clarify address profiles and route statistics contracts 2026-10-24 12:18:30 +02:00
evgeny 30a69712fc Align route table and observation documentation 2026-10-24 12:17:44 +02:00
evgeny 27cf6ae365 docs(proxy): document per-instance datagram contexts 2026-10-24 12:16:47 +02:00
evgeny 1ad8ff73ad Document routing helper ownership and wire contracts 2026-10-24 12:16:31 +02:00
evgeny 0bc0d6cc62 Enforce disjoint IPv4 route insertion atomically 2026-10-24 12:15:29 +02:00
evgeny 23cec465bf docs(proxy): specify TCP lifecycle and UDP ownership 2026-10-24 12:14:42 +02:00
evgeny a4abe30b18 docs(proxy): clarify flow control and HTTP parser contracts 2026-10-24 12:13:05 +02:00
evgeny 34d1dcb7c8 Document send scanning, retry rounds, and fast stall recovery 2026-10-24 12:01:20 +02:00
evgeny 93bf846fc4 Preserve retry priority during bounded burst measurements 2026-10-24 11:46:42 +02:00
evgeny c87cc6e4a2 Match the input waiter callback signature 2026-10-24 11:41:39 +02:00
evgeny 1fbd1e466b Verify retry history, stall recovery, and admission callbacks 2026-10-24 11:39:31 +02:00
evgeny b4d5da1df2 Wait for both configured RTOs in queue bypass regression 2026-10-24 11:35:25 +02:00
evgeny ff74ac8295 Scan past blocked DATA while prioritizing sendable retries 2026-10-24 11:31:46 +02:00
evgeny dcd6cd93c4 Select unused retry paths before starting another round 2026-10-24 11:29:13 +02:00
evgeny d439ee7ca7 Track stalled DATA paths and accepted retry rounds safely 2026-10-24 11:28:29 +02:00
evgeny 39ee5b392b Define retry path history and fast stall state contracts 2026-10-24 11:27:48 +02:00
evgeny acde6bda9d Test send queue bypass, retry priority, and bounded admission 2026-10-24 11:22:28 +02:00
evgeny 8167e0e5f5 Record recovery stage checks and repeated stalled-path cycles 2026-10-24 10:43:25 +02:00
evgeny 5a32d08ffd Buffer retry choice diagnostics until measurement completes 2026-10-24 10:32:44 +02:00
evgeny b98b87ea12 Explain retry choices between stalled multipath channels 2026-10-24 10:26:14 +02:00
evgeny 05d3fa30d9 Record path history for the fragment blocking delivery 2026-10-24 10:19:36 +02:00
evgeny 516ed04897 Identify the fragment behind maximum multipath message latency 2026-10-24 10:18:11 +02:00
evgeny 1d295c7d3a Measure multipath recovery stages separately from RTO waits 2026-10-24 10:05:13 +02:00
evgeny 1c6a7e7bf9 Remove speculative early retries from the ETCP plan 2026-10-24 09:56:54 +02:00
evgeny f1f4976222 Record retry recovery status and full regression results 2026-10-24 09:48:19 +02:00
evgeny 14515ca446 Document retry wait policy and fault recovery measurements 2026-10-24 09:46:38 +02:00
evgeny 8dd03c2b5c Wait for another UP path before retrying ETCP DATA 2026-10-24 09:38:20 +02:00
evgeny 412b9bc713 Test retry waiting for another available ETCP path 2026-10-24 09:34:21 +02:00
evgeny ff2860ffbc Record pacer validation and remaining multipath failures 2026-10-24 09:09:42 +02:00
evgeny c7a530092d Check pacer reset callback against its actual contract 2026-10-24 02:54:41 +02:00
evgeny deac10e3f6 Wake ETCP pacer at its first permitted transmit time 2026-10-24 02:49:25 +02:00
evgeny 42c4195f2e Test pacer eligibility boundaries and readiness lifecycle 2026-10-24 02:25:23 +02:00
evgeny ce3d942efe Record multipath baseline and verify pacer wakeup defect 2026-10-24 02:17:38 +02:00
evgeny a22a27b7a9 Record validated signature lifecycle fix and exact contracts 2026-10-24 01:15:49 +02:00
evgeny 7d57b484d8 Focus signature test logs on lifecycle and failure stages 2026-10-24 01:10:12 +02:00
evgeny 44acb5aecf Document streaming signature state ownership and retries 2026-10-24 01:03:24 +02:00
evgeny 5d11f90cd4 Make streaming signature initialization and cleanup safe 2026-10-24 01:02:10 +02:00
evgeny 4824f3523d Test streaming signature ownership and OpenSSL failures 2026-10-24 01:00:36 +02:00
evgeny 5a7823e6ef Record streaming signature OOM defect and completed temp fix 2026-10-24 00:46:40 +02:00
evgeny 5792db996c Clarify crypto key derivation and actual module dependencies 2026-10-24 00:44:29 +02:00
evgeny 16a33ac9f7 Correct remaining crypto examples and streaming signature buffer contract 2026-10-24 00:37:18 +02:00
evgeny 3afd31e561 Align crypto documentation with random CCM nonces and public-key node IDs 2026-10-24 00:35:13 +02:00
evgeny 2715faffff Document receiver-bounded BBR samples and diagnostic input contracts 2026-10-24 00:33:19 +02:00
evgeny 9459b43211 Remove stale pacing and handshake descriptions from ETCP protocol specification 2026-10-24 00:32:42 +02:00
evgeny 964f6cb045 Correct ETCP diagnostic filters and state dump documentation 2026-10-24 00:30:33 +02:00
evgeny bed99abbe9 Clarify STCP client ownership, ping lifetime and handshake byte order 2026-10-24 00:28:58 +02:00
evgeny d6eecd6f1c Document STCP listener arguments, accepted ownership and current handshake phases 2026-10-24 00:27:56 +02:00
evgeny ecdd767934 Align connection documentation with current UDP sessions and keepalive wire format 2026-10-24 00:27:14 +02:00
evgeny 1cf2cc10dd Keep file I/O return-value overview consistent with orphan cleanup API 2026-10-24 00:21:25 +02:00
evgeny 39f9d6a0e9 Keep active block and worker temporaries during media cache cleanup 2026-10-24 00:16:57 +02:00
evgeny e84c66a3d3 Reproduce orphan cleanup during a real encrypted attachment transfer 2026-10-24 00:15:16 +02:00
evgeny e195894048 Protect owned temporary files from concurrent orphan removal 2026-10-24 00:13:18 +02:00
evgeny ee437b9473 Align ETCP header declarations, timestamp units and UDP contracts with code 2026-10-24 00:06:45 +02:00
evgeny 299c613760 Correct ETCP API callback and datagram ownership documentation 2026-10-24 00:06:00 +02:00
evgeny 74b63cc315 Verify ETCP registry identity and failure ownership invariants 2026-10-24 00:01:02 +02:00
evgeny 032f8e83b2 Publish incoming UDP peers before callbacks and preserve accepted ownership 2026-10-23 23:57:51 +02:00
evgeny c7d7789a58 Reuse ETCP registry entries and reject duplicate peer indexing 2026-10-23 23:57:32 +02:00
evgeny fb995db489 Cover UDP accept cancellation with surviving paths and NCD owners 2026-10-23 23:50:39 +02:00
evgeny 942736d604 Check accepted and rejected MTU boundaries in both UDP handshake directions 2026-10-23 23:42:49 +02:00
evgeny b8021efed8 Validate UDP handshake MTU and nonzero path IDs before state updates 2026-10-23 23:41:58 +02:00
evgeny 1260884485 Exercise invalid UDP INIT path identifiers and MTU limits 2026-10-23 23:40:37 +02:00
evgeny 52d9077bb5 Describe retained link scopes and callback-safe RX timeouts 2026-10-23 23:37:44 +02:00
evgeny 519a2ee242 Cover UDP callback deletion, connection close and path replacement 2026-10-23 23:35:55 +02:00
evgeny 6d6ec7e725 Keep RX timeout and link-status callbacks inside retained link scopes 2026-10-23 23:31:16 +02:00
evgeny d0a168f89e Retain ETCP links across callbacks and release closed paths on scope exit 2026-10-23 23:30:43 +02:00
evgeny 5ccd47dd17 Bind incoming UDP INIT identity to the authenticated key 2026-10-23 23:17:25 +02:00
evgeny 2f6ff9303e Reject authenticated INIT requests claiming another node identity 2026-10-23 23:17:01 +02:00
evgeny d9aede4138 Drain pending UDP traffic before snapshotting INIT validation state 2026-10-23 23:13:03 +02:00
evgeny 0860b1e06d Validate the complete UDP INIT request body before reading fields 2026-10-23 23:09:27 +02:00
evgeny 10927b1d08 Allow early wire rejection in INIT request boundary tests 2026-10-23 23:06:23 +02:00
evgeny 3a8cc8a326 Exercise encrypted UDP INIT request body boundaries 2026-10-23 23:03:48 +02:00
evgeny bf7464a4d9 Document connection ownership after a cancelled TCP accept 2026-10-23 22:53:58 +02:00
evgeny e51badebcb Preserve active owners and paths when an incoming TCP link is cancelled 2026-10-23 22:53:36 +02:00
evgeny d5d103148f Test ownership handoff while cancelling an incoming TCP path 2026-10-23 22:52:40 +02:00
evgeny d5721563fc Clarify NEW cancellation and subscription mutation semantics 2026-10-23 22:43:09 +02:00
evgeny 274554f7a5 Cover TCP creation cancellation and self-unsubscription on both roles 2026-10-23 22:42:20 +02:00
evgeny 8fe1011da2 Document constructor cancellation and link memory ownership 2026-10-23 22:41:42 +02:00
evgeny 21a4dd7a70 Exercise callback unsubscription and nested dispatch on all ETCP chains 2026-10-23 22:40:47 +02:00
evgeny 33912355d6 Keep removed ETCP subscriptions until the outer dispatch returns 2026-10-23 22:39:56 +02:00
evgeny 5178f7abc6 Define instance callback dispatch lifetime for safe unsubscription 2026-10-23 22:39:06 +02:00
evgeny d0ee0341c5 Verify cancelled link constructors and guard UDP handshake callbacks 2026-10-23 22:36:39 +02:00
evgeny a2861b0570 Keep cancelled links alive until their constructor returns 2026-10-23 22:35:14 +02:00
evgeny a51c080407 Return NULL when callbacks cancel ETCP connection creation 2026-10-23 22:34:46 +02:00
evgeny 2ea4fb94ab Test nested deletion of the current and neighboring ETCP paths 2026-10-23 22:03:58 +02:00
evgeny 986193055e Suppress stale connection UP after its callback removes the last path 2026-10-23 22:03:29 +02:00
evgeny a43d478495 Cover close from connection INIT and UP callbacks on both roles 2026-10-23 22:02:44 +02:00
evgeny bf5a128a05 Correct STCP close contracts and sanitizer issues in its test 2026-10-23 22:01:48 +02:00
evgeny 477d8f995b Document STCP adapter ownership, callbacks and reconnect lifecycle 2026-10-23 21:59:12 +02:00
evgeny 03d69cb772 Verify TCP retry timing, recovery and cancellation end to end 2026-10-23 21:58:27 +02:00
evgeny f5e4c78b8c Exercise repeated close during the server link teardown event 2026-10-23 21:57:10 +02:00
evgeny 425e1a527b Provide the peer snapshot for the incoming test owner 2026-10-23 21:56:35 +02:00
evgeny f1e3c2c08a Hold the incoming connection before exercising DOWN callbacks 2026-10-23 21:55:54 +02:00
evgeny bd9f1bb0c9 Flush cancelled timers in teardown tests and clarify adapter close 2026-10-23 21:54:49 +02:00
evgeny 1fb52d3f5b Report active resources when callback teardown is unbalanced 2026-10-23 21:54:15 +02:00
evgeny 4614577d19 Stop readiness publication after callback close and rescan teardown links 2026-10-23 21:49:11 +02:00
evgeny f37221107d Guard TCP link transitions across callbacks and unify reconnect backoff 2026-10-23 21:48:11 +02:00
evgeny 42e7b9b1b6 Own STCP adapter queues and report connection failures before READY 2026-10-23 21:46:12 +02:00
evgeny 7753a0f11e Include the raw STCP server API in adapter regression tests 2026-10-23 21:43:17 +02:00
evgeny 4bfec7257f Cover TCP callback teardown on both roles and guard link close reentry 2026-10-23 21:40:43 +02:00
evgeny 2cad81050d Exercise early STCP adapter failure and cancellation callbacks 2026-10-23 21:39:32 +02:00
evgeny 18f10b23b3 Record compact attempt validation and aggregation check 2026-10-23 19:34:46 +02:00
evgeny a3eeebbc52 Clarify attempt reservation ownership on epoch exhaustion 2026-10-23 19:33:11 +02:00
evgeny 85c92e35a8 Update multipath contract for compact attempt pairs 2026-10-23 19:30:22 +02:00
evgeny be95e93a36 Reject old encrypted ACKs when compact attempt pairs restart in a new epoch 2026-10-23 19:27:06 +02:00
evgeny 7c09bfca7f Stop packet construction when input callbacks restart the stream 2026-10-23 19:26:00 +02:00
evgeny 77a737fd71 Document compact attempt wire layout and epoch reuse protection 2026-10-23 19:25:20 +02:00
evgeny 9a9517deab Exercise ACK splitting beyond compact entry capacity 2026-10-23 19:24:52 +02:00
evgeny b73d6e91e2 Verify compact attempt isolation, wire boundaries and exhaustion recovery 2026-10-23 19:23:30 +02:00
evgeny 0987d9dd04 Adapt encrypted session and window fixtures to compact attempt fields 2026-10-23 19:20:49 +02:00
evgeny ccbd214c97 Encode 16-bit attempt numbers and guard pair reuse by session epochs 2026-10-23 19:19:54 +02:00
evgeny 6414cb15ef Define compact per-fragment ETCP attempt numbers 2026-10-23 19:19:07 +02:00
evgeny 8c3fcfd1c8 Log fragment bytes and session epochs on normalizer desync 2026-10-23 18:15:17 +02:00
evgeny 1b7d314d85 Record bandwidth-only correction validation and remaining speed limits 2026-10-23 16:48:47 +02:00
evgeny ea5a0b7d5a Describe receiver-clock bandwidth bounds and ACK wire format 2026-10-23 16:44:07 +02:00
evgeny 6fc964031c Check ACK receiver point diagnostics at buffer boundaries 2026-10-23 16:40:52 +02:00
evgeny 4bf47ca357 Exercise receiver bandwidth bounds and ACK progress framing 2026-10-23 16:39:12 +02:00
evgeny ea4a92125b Carry receiver progress only in ACKs with attempt confirmations 2026-10-23 16:23:20 +02:00
evgeny 5586528555 Bound ETCP bandwidth samples by receiver delivery progress 2026-10-23 16:22:13 +02:00
evgeny e8d9d683dc Record duplex plan trials and measured ACK bandwidth costs 2026-10-23 16:10:46 +02:00
evgeny cc01457957 Record verified INIT recovery and BGP regression results 2026-10-23 14:24:31 +02:00
evgeny 5b8aba9c8b Drive callback deletion through the public reinit transition 2026-10-23 14:19:53 +02:00
evgeny f5d67d5240 Test link deletion from INIT and keepalive callbacks 2026-10-23 14:19:24 +02:00
evgeny 35ef504423 Document INIT liveness and response validation contracts 2026-10-23 14:16:28 +02:00
evgeny a87d3116af Validate INIT response body before updating peer state 2026-10-23 14:14:53 +02:00
evgeny c5f743a09d Cover INIT liveness with an independent healthy link 2026-10-23 14:01:57 +02:00
evgeny b167a27e85 Document RX ownership and limit readiness wakeups to transitions 2026-10-23 13:48:09 +02:00
evgeny f00a5bd306 Apply INIT reachability before reply and publish guarded RX transitions 2026-10-23 13:45:23 +02:00
evgeny 608caf01c1 Initialize the liveness fixture crypto and drain cancelled timers 2026-10-23 13:41:59 +02:00
evgeny e801fce2c6 Add encrypted UDP INIT liveness and one-way recovery regression 2026-10-23 13:38:36 +02:00
evgeny e89948f5ed Include the lowest reverse solo rate in measurement summary 2026-10-23 13:20:44 +02:00
evgeny 3c7b59ef02 Report three-run multipath rates and confirmed INIT liveness failure 2026-10-23 13:20:15 +02:00
evgeny 54fb4185f1 Identify one-way INIT liveness defect behind intermittent BGP failure 2026-10-23 13:14:51 +02:00
evgeny ac264c254c Expose transport topology in BGP route exchange failures 2026-10-23 13:13:47 +02:00
evgeny 5403647aee Record full regression results after retransmission timeout change 2026-10-23 13:05:22 +02:00
evgeny 3a007fbb29 Record jitter control and the cost of a shorter retransmission margin 2026-10-23 13:02:18 +02:00
evgeny 92e9281623 Record timeout matrix improvements and outstanding latency thresholds 2026-10-23 13:01:37 +02:00
evgeny e0f28bf851 Document reduced RTT multiplier and jitter margin for RTO 2026-10-23 12:52:59 +02:00
evgeny 9dbef48eb3 Use RTT jitter and fixed margin for ETCP retransmission timeout 2026-10-23 12:52:35 +02:00
evgeny e84e17c396 Record successful proxy burst and load validation after OOM changes 2026-10-23 12:46:10 +02:00
evgeny 9cc921f615 Record full regression failures and diagnose active media temp deletion 2026-10-23 12:45:38 +02:00
evgeny 0d5e9332e3 Clarify connection references versus active callback lifetime 2026-10-23 12:43:26 +02:00
evgeny b1e94eff34 Describe OOM session interruption and normalizer ownership precisely 2026-10-23 12:42:05 +02:00
evgeny bbe43b9842 Record completed fail-fast OOM recovery and remaining multipath work 2026-10-23 12:41:14 +02:00
evgeny 3bba05d354 Give encrypted DATA fixture a valid keepalive receive timeout 2026-10-23 12:36:20 +02:00
evgeny d43716933f Test encrypted two-sided recovery after normalizer OOM 2026-10-23 12:33:58 +02:00
evgeny 3c18e594d1 Keep the session deadline unchanged across handshake retries 2026-10-23 12:32:57 +02:00
evgeny 23d426fd0c Document fail-fast OOM and session interruption contracts 2026-10-23 12:32:56 +02:00
evgeny f221fa5a89 Exercise normalizer waiter allocation failure on a busy ETCP queue 2026-10-23 12:30:38 +02:00
evgeny 6e33675503 Verify OOM session abort, recovery and reentrant callback teardown 2026-10-23 12:29:29 +02:00
evgeny 76398d204a Add deterministic normalizer and restart fault injection hooks 2026-10-23 12:28:13 +02:00
evgeny d2b195473d Test queue discard without allocation or stale callbacks 2026-10-23 12:27:38 +02:00
evgeny caf37e9541 Make stream restart terminate explicitly if session scheduling fails 2026-10-23 12:24:48 +02:00
evgeny 316180c276 Abort normalizer sessions on OOM and guard reentrant delivery callbacks 2026-10-23 12:24:48 +02:00
evgeny 5f085b2086 Discard failed ETCP streams without allocating or replaying fragments 2026-10-23 12:22:22 +02:00
evgeny 466a56b499 Add allocation-free queue discard for terminal stream resets 2026-10-23 12:20:34 +02:00
evgeny 0989eff73d Record complete proxy integration checks and normalizer ownership fix outline 2026-10-23 11:32:10 +02:00
evgeny 187aa02b49 Record passing full regression and eight sanitizer checks 2026-10-23 11:29:53 +02:00
evgeny 0aaf6dfea0 Check metrics aggregate ACK queues and RTO state across paths 2026-10-23 11:26:45 +02:00
evgeny 9c40b489cf Record implemented multipath foundation and remaining reliability blockers 2026-10-23 11:25:13 +02:00
evgeny ce798a193e Remove stale fixture pointer and verify full transmission IDs in packet dumps 2026-10-23 11:22:37 +02:00
evgeny ddba151aa5 Adapt control metrics fixture to per-link ACK ownership 2026-10-23 11:17:20 +02:00
evgeny 2fddf839af Show transmission identity and frontier queries in ETCP packet diagnostics 2026-10-23 11:13:26 +02:00
evgeny 7bb43c42d6 Document per-path attempt ACKs, loss timers, pacing and memory bounds 2026-10-23 11:12:40 +02:00
evgeny b442d131c9 Exercise bounded attempt and ACK storage after logical delivery 2026-10-23 11:10:19 +02:00
evgeny 783646a967 Apply attempt budgets before selecting DATA paths 2026-10-23 11:09:28 +02:00
evgeny b74ff2633d Bound path ACK queues and physical attempt memory 2026-10-23 11:09:28 +02:00
evgeny b97169de19 Verify DATA pacing independently of piggyback ACK size 2026-10-23 11:04:11 +02:00
evgeny 72f48d1f14 Keep DATA pacing units consistent and test startup delay exit 2026-10-23 10:59:30 +02:00
evgeny 227104e224 Leave BBR startup after a full round of excessive queue delay 2026-10-23 10:58:38 +02:00
evgeny d57a729b92 Preserve bounded pacing credit across millisecond timer rounding 2026-10-23 10:45:39 +02:00
evgeny 3ca9926c48 Release synthetic path queues in the session-timeout fixture 2026-10-23 10:42:43 +02:00
evgeny 4c9a32d865 Observe peer-window recovery after the deferred queue resume 2026-10-23 10:40:48 +02:00
evgeny 5e436975c6 Exercise retry rotation, late attempt ACKs and receiver admission faults 2026-10-23 10:38:23 +02:00
evgeny a4a9ae7b0a Return receive-window query replies on the requesting path 2026-10-23 10:35:38 +02:00
evgeny 34a31f63be Update encrypted session fixtures and multipath observation for attempt IDs 2026-10-23 10:29:20 +02:00
evgeny 75485bf7bf Aggregate pending path ACKs in chat transport status 2026-10-23 10:28:17 +02:00
evgeny 432017cc22 Verify logical delivery and physical window counters independently 2026-10-23 10:27:38 +02:00
evgeny 147648ffd0 Expose per-path attempts and ACK queues in transport diagnostics 2026-10-23 10:25:27 +02:00
evgeny 1b3c4552fb Account for transmission IDs in MTU and packet diagnostics 2026-10-23 10:24:29 +02:00
evgeny cc510fc74c Separate stream delivery from path ACKs and acknowledge retained DATA 2026-10-23 10:23:14 +02:00
evgeny abe3d4bc89 Rotate retransmissions per fragment and commit only accepted sends 2026-10-23 10:14:46 +02:00
evgeny 7bc2ac5a46 Implement per-path attempt accounting and isolated ACK delivery samples 2026-10-23 10:13:22 +02:00
evgeny b68e0ac3db Define independent logical fragments and per-path transmission attempts 2026-10-23 10:09:44 +02:00
evgeny 3c44c3d7bc Keep unknown BBR bandwidth from imposing a one-byte pacing stall 2026-10-23 02:32:36 +02:00
evgeny e21cd26511 Apply BBR pacing through one owner and keep burst estimates diagnostic 2026-10-23 02:28:45 +02:00
evgeny 7e413db1e1 Keep pacing in bytes per second and reprice outstanding shaper debt 2026-10-23 02:28:11 +02:00
evgeny b39a861a57 Initialize STARTUP pacing from the actual initial DATA window 2026-10-23 02:24:10 +02:00
evgeny b349d7b7b2 Document agreed retransmission bounds and verified timer behavior 2026-10-23 02:21:43 +02:00
evgeny c3ac337ef0 Clamp ETCP retransmission timeout to 10 ms through 1 second 2026-10-23 02:20:10 +02:00
evgeny 4aae1f6151 Specify retry path rotation and close ACK ownership gaps 2026-10-23 02:08:04 +02:00
evgeny 259dfa35d9 Record RTT feedback experiments and refine multipath recovery plan 2026-10-23 01:56:01 +02:00
evgeny 7e0a0905e5 Document BBR queue time policy and its physical delay limits 2026-10-23 01:03:27 +02:00
evgeny 34e3d9bba0 Verify queue budget saturation and the BBR fast path contract 2026-10-23 01:02:15 +02:00
evgeny 599d8ad421 Bound BBR probe windows by the steady-state queue time budget 2026-10-23 01:01:25 +02:00
evgeny 4035794631 Define and test the BBR steady-state queue time budget 2026-10-23 01:00:36 +02:00
evgeny 5f406c2a41 Document BBR queue budget conflict with the fixed latency target 2026-10-23 00:58:29 +02:00
evgeny 94d6dd05c8 Expose BBR bandwidth and ACK budget alongside physical queue peaks 2026-10-23 00:54:27 +02:00
evgeny 67ae4ecf11 Record full regression results and reproducible NAT profile failures 2026-10-23 00:51:44 +02:00
evgeny d0f122f4d8 Record verified RTT probe fixes and remaining multipath failures 2026-10-23 00:49:02 +02:00
evgeny 08b6b2e2a1 Document DATA MSS and shared BBR transport window contracts 2026-10-23 00:45:09 +02:00
evgeny 5298fe9f6a Keep BBR loss bounds above the DATA window minimum 2026-10-23 00:43:54 +02:00
evgeny aefa8ff680 Check BBR loss bounds against the minimum DATA window 2026-10-23 00:43:31 +02:00
evgeny 0f23076f48 Apply BBR DATA windows consistently during startup and RTT probes 2026-10-23 00:42:45 +02:00
evgeny 92a535e009 Cover BBR probe drain and transport DATA window consistency 2026-10-23 00:42:02 +02:00
evgeny 519d6e4eaf Record verified BBR fixes and remaining multipath contract conflicts 2026-10-23 00:25:55 +02:00
evgeny 716db3a820 Saturate BBR byte windows instead of wrapping at large BDP 2026-10-23 00:24:35 +02:00
evgeny 3d6f855d34 Keep BBR probing and aggregation counters dimensionally consistent in bytes 2026-10-23 00:17:14 +02:00
evgeny 229e992695 Cover probing byte budgets and ACK aggregation beyond 64KiB 2026-10-23 00:16:40 +02:00
evgeny a79c724110 Grow BBR probe inflight bounds in MSS-sized byte increments 2026-10-23 00:15:46 +02:00
evgeny 6b1298aa62 Reproduce byte-sized instead of MSS-sized BBR probing growth 2026-10-23 00:15:28 +02:00
evgeny 0364abb00e Log sampled BBR model state without flooding transport diagnostics 2026-10-23 00:12:28 +02:00
evgeny f8d532b04d Describe ACK handling and bounded DATA pacing in the ETCP protocol 2026-10-23 00:10:01 +02:00
evgeny 4dba742149 Document BBR byte units and flight-based delivery rate samples 2026-10-23 00:10:00 +02:00
evgeny 88eb0f2108 Require multipath goodput without inflating channel queues 2026-10-23 00:08:15 +02:00
evgeny ade0e93f7f Measure actual channel queueing delay independently of propagation RTT 2026-10-23 00:08:15 +02:00
evgeny addff8547e Keep the ACK compression fixture within its known retransmission deadline 2026-10-23 00:06:30 +02:00
evgeny 1c18bdc9ab Measure BBR delivery over packet flights instead of inter-ACK gaps 2026-10-23 00:06:30 +02:00
evgeny f3008b7aba Snapshot delivery and send intervals for per-link BBR rate measurement 2026-10-23 00:06:30 +02:00
evgeny c2f4f048d7 Reproduce inflated delivery-rate samples when ACKs arrive together 2026-10-23 00:05:48 +02:00
evgeny 3c38072b9b Send ACK independently of the local outgoing DATA congestion pacer 2026-10-23 00:03:29 +02:00
evgeny 4cfd0ec89f Identify DATA in local datagram metadata without changing the wire header 2026-10-23 00:03:29 +02:00
evgeny 08c42e62ef Reproduce ACK starvation behind the reverse-direction DATA pacer 2026-10-23 00:02:57 +02:00
evgeny dd153264e1 Verify byte-rate scaling at multiple MTUs and multi-gigabit rates 2026-10-23 00:00:40 +02:00
evgeny 6f87ea1426 Keep BBR pacing and BDP in byte units without a second MSS factor 2026-10-22 23:59:57 +02:00
evgeny 6fec5d6d98 Reproduce MSS-dependent BBR pacing and BDP with a dimensional regression 2026-10-22 23:59:20 +02:00
evgeny 9b9a9f2e00 Record final multipath fault results and sanitizer validation 2026-10-22 23:41:45 +02:00
evgeny 27a7b7bf25 Declare the multipath phony target without overlapping Automake conditions 2026-10-22 23:40:12 +02:00
evgeny c9ba018a0d Bound fault steady goodput by newly received unique DATA 2026-10-22 23:37:24 +02:00
evgeny df5f6263bd Measure short HOLD across resume and arm faults before propagation completes 2026-10-22 23:37:02 +02:00
evgeny 0b5a892a88 Document multipath acceptance criteria and reproduced protocol limitations 2026-10-22 23:36:21 +02:00
evgeny 076016f34a Expose multipath queue accounting and add a dedicated long-running check target 2026-10-22 23:34:20 +02:00
evgeny 8417b1955c Document emulator queue bounds and account for allocation failures 2026-10-22 23:33:14 +02:00
evgeny 67322582f6 Report delivery failures per scenario without hiding subsequent channel cases 2026-10-22 23:32:34 +02:00
evgeny 439361cb52 Exclude previously buffered data from multipath utilization results 2026-10-22 23:31:02 +02:00
evgeny 6e350760d1 Check active channel stalls, delivery deadlines and delayed packet recovery 2026-10-22 23:29:29 +02:00
evgeny 672f04b833 Exercise real ETCP multipath against independent bandwidth and RTT profiles 2026-10-22 23:23:05 +02:00
evgeny f5cab5a14e Calibrate dummynet bandwidth and verify stalled channel lifecycle 2026-10-22 23:19:01 +02:00
evgeny f5f6ff50af Make dummynet bandwidth timing cumulative and add bounded DROP/HOLD modes 2026-10-22 23:18:11 +02:00
evgeny 62f4850968 Record successful full ETCP regression validation 2026-10-22 23:04:00 +02:00
evgeny 082d9d3960 Record STCP SIGPIPE regression and sanitizer validation 2026-10-22 23:02:42 +02:00
evgeny 05a5b6c2a7 Exercise STCP writes with default SIGPIPE disposition 2026-10-22 22:59:45 +02:00
evgeny fdcf92be04 Prevent SIGPIPE from terminating embedded STCP transports 2026-10-22 22:59:44 +02:00
evgeny 11aa760d47 Document ETCP window ownership and completed connection fixes 2026-10-22 22:57:06 +02:00
evgeny bc27352710 Remove stale references to the legacy connect installer 2026-10-22 22:53:55 +02:00
evgeny 0a00bd1c90 Clarify readiness contracts and stop on corrupt accounting 2026-10-22 22:53:30 +02:00
evgeny e2ee0d81dd Wait for both ETCP streams before starting Merkle tests 2026-10-22 22:52:14 +02:00
evgeny 6afc57569a Test zero-delay sender wakeups and failure injection 2026-10-22 22:50:38 +02:00
evgeny ccb3821e2f Schedule ordinary ETCP sends without timer latency 2026-10-22 22:50:04 +02:00
evgeny 29f9a97552 Use valid global options in REALITY config fixtures 2026-10-22 22:48:53 +02:00
evgeny f37ac2c637 Verify deferred teardown when the TX timer cannot start 2026-10-22 22:47:50 +02:00
evgeny 0ef0553598 Coalesce useful TX wakeups and defer failure teardown safely 2026-10-22 22:45:58 +02:00
evgeny f1c88ad375 Document congestion configuration and protect key diagnostics 2026-10-22 22:40:47 +02:00
evgeny 17c92e1745 Diagnose adopted transports and isolate traffic test commands 2026-10-22 22:39:43 +02:00
evgeny 34e346463d Cover initial UP, pacing and bidirectional tight windows 2026-10-22 22:38:20 +02:00
evgeny ef11d3b677 Preserve initial readiness while sender waits for a session 2026-10-22 22:36:53 +02:00
evgeny 2689931826 Inject allocation failures through the actual pool symbol 2026-10-22 22:34:07 +02:00
evgeny 133ea8d120 Wake sender after preparing each new fragment 2026-10-22 22:33:43 +02:00
evgeny 75ff7c4ce3 Exercise DATA windows, ACKs, retries and sender wakeups 2026-10-22 22:33:11 +02:00
evgeny 86a0f041c7 Validate congestion limits and guard window arithmetic 2026-10-22 22:31:12 +02:00
evgeny c1f07ec6ae Enforce per-link DATA windows without blocking ACKs 2026-10-22 22:29:31 +02:00
evgeny 50d5486a9f Define per-link accounting and deferred sender contracts 2026-10-22 22:26:51 +02:00
evgeny 036cf43918 Build and document direct connections through NCD 2026-10-22 22:25:52 +02:00
evgeny fc5b3911f3 Detach ETCP core from obsolete connect contexts 2026-10-22 22:25:39 +02:00
evgeny 008f499367 Remove obsolete parallel ETCP connection installer 2026-10-22 22:25:39 +02:00
evgeny 8169322d56 Move direct transport tests to NCD ownership 2026-10-22 22:24:45 +02:00
evgeny d84ab69465 Verify link selection mismatch with valid congestion limits 2026-10-22 21:32:34 +02:00
evgeny 91bb95a981 Record ETCP and STCP header audit findings 2026-10-22 21:30:28 +02:00
evgeny 03f4cd7939 Record validated media supernode replication implementation 2026-10-22 21:21:43 +02:00
evgeny 71d3b017e6 Clarify local media catalog seeding and channel cleanup contracts 2026-10-22 21:20:21 +02:00
evgeny 8230eb4de7 Test final-page update races and replication read failures 2026-10-22 21:16:59 +02:00
evgeny bc149497f3 Document media replication protocol and resource ownership 2026-10-22 21:15:55 +02:00
evgeny 0bcdb9930a Make media send queue policy explicit and document announcement errors 2026-10-22 21:14:42 +02:00
evgeny f2283eff6b Wait for actual retry requests independently of change hints 2026-10-22 21:12:58 +02:00
evgeny a011c57237 Cover replication retries, source reset and router backpressure 2026-10-22 21:10:44 +02:00
evgeny 9e2a1e5208 Handle automatic SQLite rollback and complete CHAT integration setup 2026-10-22 21:09:16 +02:00
evgeny d6d8ffc4a8 Require role subscription and initialize real chat test contexts 2026-10-22 21:07:18 +02:00
evgeny 14b01964b1 Initialize media test dependencies and await committed sync 2026-10-22 21:06:15 +02:00
evgeny 7fb9b43e9e Validate media role changes through signed CHAT membership 2026-10-22 21:02:57 +02:00
evgeny 63c0b9a655 Run media integration replication in its actual CHAT group 2026-10-22 21:01:24 +02:00
evgeny 00502bf4d4 Exercise real media replication pages, rollback and catalog lifecycle 2026-10-22 21:00:48 +02:00
evgeny d3bc77922b Initialize replication router queues before waiting for room 2026-10-22 20:55:25 +02:00
evgeny b4b11d6086 Implement atomic group-scoped media catalog replication 2026-10-22 20:54:37 +02:00
evgeny b47a82e3ac Define bounded receiver-driven media replication protocol 2026-10-22 20:45:14 +02:00
evgeny 04dc53672a Add regression for media availability group isolation 2026-10-22 20:43:51 +02:00
evgeny 964a938437 Record reproduced media replication failures and correct cursor audit 2026-10-22 20:11:06 +02:00
evgeny e8843d9499 Track remaining media supernode replication audit separately 2026-10-22 19:53:31 +02:00
evgeny ecba318dec Record validated media block ownership and relay fixes 2026-10-22 19:48:47 +02:00
evgeny 1aec478787 Drive relay generation wakeup through actual queue consumption 2026-10-22 19:46:30 +02:00
evgeny 8f97cf8070 Verify old relay readers survive a new download generation independently 2026-10-22 19:45:45 +02:00
evgeny bd0260040c Replace obsolete media relay description with current attempt and buffer contracts 2026-10-22 19:43:59 +02:00
evgeny 3b24e7e207 Describe media source lifetime, callback ownership and publication ordering 2026-10-22 19:40:38 +02:00
evgeny 993e22085a Scope libc fault-injection regression target to Linux 2026-10-22 19:39:34 +02:00
evgeny 00e0421e56 Update media wire-size assertions and cover fortified read fault injection 2026-10-22 19:38:56 +02:00
evgeny fabeb770a7 Verify media source admission, redirect bounds and transmit I/O failure cleanup 2026-10-22 19:37:28 +02:00
evgeny 47addfeffc Cover terminal media registration failures and relay admission lifetime 2026-10-22 19:35:45 +02:00
evgeny 02e1526115 Remove redundant embedded download entry and update service-stop request 2026-10-22 19:33:49 +02:00
evgeny c81cc8b9ca Document media attempt validation and reserve before tracking outgoing writes 2026-10-22 19:33:12 +02:00
evgeny 99389f4bd3 Bound relay readers independently and redirect only to matching block recipients 2026-10-22 19:32:15 +02:00
evgeny b09a020855 Exercise media block identity, I/O failure, reentrancy and relay backpressure 2026-10-22 19:30:59 +02:00
evgeny 090e7db598 Expose transport queue control in media regression fixtures 2026-10-22 19:27:37 +02:00
evgeny 5215163a37 Share authenticated media fixtures for adversarial delivery regressions 2026-10-22 19:25:24 +02:00
evgeny 1c1ab24a27 Test real truncated-block assembly and balance media admission ownership 2026-10-22 19:24:17 +02:00
evgeny 353752165c Align media integration inputs with routed block identity 2026-10-22 19:23:53 +02:00
evgeny b1a3d0c6cd Scope media retry responses to active block attempts 2026-10-22 19:17:36 +02:00
evgeny 16333b989d Replace permissive media download fixtures with verified block inputs 2026-10-22 19:16:23 +02:00
evgeny d2bf40e11a Use authenticated block metadata in media query fixtures 2026-10-22 19:15:17 +02:00
evgeny d0a401e166 Validate received blocks and publish complete verified media atomically 2026-10-22 19:14:12 +02:00
evgeny 4edf72ea14 Create independent block attempts and cancel channel downloads safely 2026-10-22 19:11:44 +02:00
evgeny 9b4974f02d Unify media source and relay transmission with owned buffers 2026-10-22 19:11:26 +02:00
evgeny f15d53947e Define media block attempts and shared byte-source ownership 2026-10-22 19:08:14 +02:00
evgeny 68129c0151 Retain media downloads across reentrant progress callbacks 2026-10-22 19:07:04 +02:00
evgeny a3a8b5b1be Add checked UTF-8 opening of existing block files for update 2026-10-22 19:03:16 +02:00
evgeny 55d2f437a0 Clarify ownership requirements for media completion callbacks 2026-10-22 18:57:48 +02:00
evgeny 108dfae82b Record reproduced media block receive and completion defects 2026-10-22 18:45:19 +02:00
evgeny 3a703d1093 Record final media QUERY full-suite validation 2026-10-22 18:31:13 +02:00
evgeny 433a091db5 Record verified media QUERY fixes and regression coverage 2026-10-22 18:31:13 +02:00
evgeny 21ebc832e1 Verify holder selection and log download resource transitions 2026-10-22 18:31:12 +02:00
evgeny a3f3b2fff2 Document media lookup lifetimes and remove obsolete shared state 2026-10-22 18:31:12 +02:00
evgeny 093e537fed Check live QUERY deadlines and deferred CM failover 2026-10-22 18:31:12 +02:00
evgeny 6a14be05f5 Verify second-block SQL failure and propagate local download errors 2026-10-22 18:31:12 +02:00
evgeny fd6155aa4a Exercise media QUERY bounds, paging, failures and peer reuse 2026-10-22 18:31:12 +02:00
evgeny f47e80571d Assert media QUERY results and preserve transport ownership in tests 2026-10-22 18:31:12 +02:00
evgeny e02c9f7727 Cancel delayed CM UP before deferring failover 2026-10-22 18:31:12 +02:00
evgeny 05ace58589 Implement bounded media lookup with independent deadlines 2026-10-22 18:31:12 +02:00
evgeny 92c514ce18 Describe bounded media lookup and peer slot state 2026-10-22 18:31:12 +02:00
evgeny 6267973d62 Define bounded media QUERY batches and complete responses 2026-10-22 18:31:12 +02:00
evgeny cecbc682a0 Move stream start and stop into the title bar 2026-10-22 18:13:43 +02:00
evgeny 07cd150b47 Merge shared Android media audio routing and microphone fixes 2026-10-22 18:04:49 +02:00
evgeny 6a1c289ab2 Keep Bluetooth SCO active for radio reception without capture 2026-10-22 17:59:11 +02:00
evgeny bb380441a3 Fix shared microphone crackle from timestamp jitter 2026-10-22 16:53:25 +02:00
evgeny 94d1e245a5 Record reproduced media QUERY bounds and response truncation defects 2026-10-22 16:47:28 +02:00
evgeny 02265644ce Record verified media index fixes and remaining QUERY audit 2026-10-22 15:48:15 +02:00
evgeny c9a3a1334b Restore shared media playback to speaker after headset loss 2026-10-22 15:24:13 +02:00
evgeny 0835c3d3cc Describe media preparation records and deferred channel cleanup 2026-10-22 15:15:52 +02:00
evgeny 34959a9657 Share atomic media commits between downloads and backfill 2026-10-22 15:14:25 +02:00
evgeny 90fab54a4a Use one atomic commit API for authored and downloaded files 2026-10-22 15:14:22 +02:00
evgeny 439011ce60 Use real media schema and validate duplicate download ownership 2026-10-22 15:13:14 +02:00
evgeny ec70908733 Check relative path limits and binding failures without truncation 2026-10-22 15:11:23 +02:00
evgeny 2b63c680b2 Verify shared Android audio ownership on a physical device 2026-10-22 15:07:26 +02:00
evgeny 44a3b33c3a Expose shared audio devices in stream viewing and document them 2026-10-22 15:07:26 +02:00
evgeny 5d10a16baa Use shared audio controls in radio and stream publication 2026-10-22 15:07:25 +02:00
evgeny 33ccba1f3f Add a common audio device selector for radio and streams 2026-10-22 15:07:25 +02:00
evgeny bebc579180 Share media playback devices and await cleanup before calls 2026-10-22 15:07:25 +02:00
evgeny a893f6b4f2 Route radio and stream capture through the shared controller 2026-10-22 15:07:25 +02:00
evgeny ecada765a2 Own Android media devices in one shared audio controller 2026-10-22 15:07:25 +02:00
evgeny b72e51accb Keep shared microphone PCM continuous across device changes 2026-10-22 15:07:25 +02:00
evgeny f123a1bdeb Document preparation ownership and log exact media index failures 2026-10-22 15:06:00 +02:00
evgeny 3bb8f76b7d Reuse the database media base when restarting chat 2026-10-22 15:03:41 +02:00
evgeny 6b54b63986 Define download start ownership and avoid access after completion 2026-10-22 15:00:41 +02:00
evgeny c08c24140c Test reentrant media events and cleanup after hash failure 2026-10-22 14:58:15 +02:00
evgeny d4efdba44e Retain failed download destinations for later cleanup 2026-10-22 14:56:07 +02:00
evgeny 41057ee9d5 Keep media task ownership through synchronous submission events 2026-10-22 14:54:18 +02:00
evgeny 87724433b1 Exercise media index failure recovery and pending channel deletion 2026-10-22 14:52:27 +02:00
evgeny 9117813c4d Preserve indexed and unfinished files during orphan cleanup 2026-10-22 14:49:11 +02:00
evgeny 15fafc42c9 Use validated paths for media submission and backfill 2026-10-22 14:46:49 +02:00
evgeny 16a5e628fd Report incomplete media cleanup separately from channel deletion 2026-10-22 14:46:15 +02:00
evgeny 32d80110cb Drain outgoing media tasks before deleting their channel 2026-10-22 14:45:29 +02:00
evgeny b3a223521c Track unfinished media destinations for channel cleanup 2026-10-22 14:44:24 +02:00
evgeny 8cba8ef3e6 Propagate media schema and downloaded registration failures 2026-10-22 14:42:44 +02:00
evgeny 113f0259ea Preserve retryable media cleanup and validate served paths 2026-10-22 14:41:45 +02:00
evgeny 889dfc411a Validate media paths and register complete files atomically 2026-10-22 14:40:30 +02:00
evgeny ad62eee10c Record media index plan constraints and late completion race 2026-10-22 14:35:56 +02:00
evgeny d68ab90f23 Record reproduced media index path and database failures 2026-10-22 14:26:49 +02:00
evgeny ad0505bd31 Record verified media primitive fixes and remaining location audit 2026-10-22 13:40:39 +02:00
evgeny 64519c41a7 Restrict fortified stdio test hook to glibc 2026-10-22 13:35:25 +02:00
evgeny 0d55c98add Inject fortified fread failures in sanitizer regressions 2026-10-22 13:34:54 +02:00
evgeny 5549a69b1c Cover failed file stream creation and document media cancellation effects 2026-10-22 13:31:13 +02:00
evgeny 1ceb0beb8d Check generated media identifiers in integration fixtures 2026-10-22 10:28:32 +02:00
evgeny 386ea85fea Log precise copy and media indexing failure operations 2026-10-22 10:27:42 +02:00
evgeny 607de2a074 Bound recursive walker stack and report exact copy failure phases 2026-10-22 10:26:56 +02:00
evgeny bf3834b95d Use existing Linux condition for media fault injection 2026-10-22 10:24:16 +02:00
evgeny 3a00caef50 Add fault injection regressions for media files and worker ownership 2026-10-22 10:23:56 +02:00
evgeny 5505afd1f3 Keep thumbnail path bounds and check UUID status in stress test 2026-10-22 10:21:41 +02:00
evgeny 0e418c7fa9 Propagate RNG errors and preserve 64-bit media sizes through callers 2026-10-22 10:20:02 +02:00
evgeny f399ded5ba Preserve files on copy errors and check media primitive failures 2026-10-22 10:18:23 +02:00
evgeny 85d96fc857 Share UTF-8 Windows path conversion with file workers 2026-10-22 10:18:22 +02:00
evgeny 3100985e4c Specify media worker ownership errors and primitive contracts 2026-10-22 10:16:57 +02:00
evgeny 6355bd1d73 Use shared file publication in video processing 2026-10-22 10:15:39 +02:00
evgeny 3ed4b73ebf Extract checked file identity and temporary publication primitives 2026-10-22 10:15:13 +02:00
evgeny 41cc04bdab Record media async primitive and contract audit findings 2026-10-22 10:07:20 +02:00
evgeny d8621c7f27 Record bootstrap regression coverage and successful validation 2026-10-22 10:02:57 +02:00
evgeny 3c49c2a4aa Initialize callback epoch for pending transport shutdown test 2026-10-22 09:59:13 +02:00
evgeny 633f1d3044 Schedule pending deadline resets from probe creation 2026-10-22 09:47:23 +02:00
evgeny 34602e3e7e Separate cold bootstrap from controlled pending probe reset 2026-10-22 09:45:48 +02:00
evgeny 330e346a7b Record bootstrap test race in TCP session initialization 2026-10-22 09:40:08 +02:00
evgeny 6d39800351 Record completed video fixes and validation coverage 2026-10-22 00:20:40 +02:00
evgeny df2f90d1f5 Allow MP4 millisecond edit rounding in audio tail regression 2026-10-22 00:17:55 +02:00
evgeny 1d6596dc61 Check resampler tail duration and actual 1080p to 720p conversion 2026-10-22 00:17:16 +02:00
evgeny 0653121fc4 Document video publication and cancellation in service lifecycle 2026-10-22 00:15:54 +02:00
evgeny 3f603534e9 Log exact video failure phases and check buffered file seeks 2026-10-22 00:11:02 +02:00
evgeny 631cc924cf Measure AAC signal onset above verified codec pre-echo level 2026-10-22 00:09:49 +02:00
evgeny 9f1825dbf8 Verify decoded video content, AAC signal timing and FFmpeg-free stubs 2026-10-22 00:08:22 +02:00
evgeny 9163025912 Test video I/O failures, audio timing, cancellation and concurrent ownership 2026-10-22 00:05:30 +02:00
evgeny 5929bb4028 Normalize unspecified PCM channel layouts before AAC setup 2026-10-22 00:03:12 +02:00
evgeny fe313cf8f8 Match FFmpeg AVIO and codec capability APIs across supported versions 2026-10-22 00:02:29 +02:00
evgeny cb9102f381 Prepare video through checked temporary output and complete codec drains 2026-10-22 00:01:47 +02:00
evgeny 9a8bc9b461 Select video regression branch from configured FFmpeg support 2026-10-21 23:59:06 +02:00
evgeny c4bf292085 Specify video publication, remux and completion contracts 2026-10-21 23:58:55 +02:00
evgeny 8d9704036f Add real video fixtures and file preservation regressions 2026-10-21 23:56:55 +02:00
evgeny fb01a9bb2e Record video audit failures and missing API contracts 2026-10-21 23:28:53 +02:00
evgeny 1d7e12c562 Avoid random HEX substring collisions in config updater assertions 2026-10-21 23:12:12 +02:00
evgeny 7c473dd500 Reject signed NAT forward IDs hidden by leading whitespace 2026-10-21 23:11:32 +02:00
evgeny 1ccb266971 Describe NAT transport backpressure, ownership and mapping holds 2026-10-21 23:08:31 +02:00
evgeny 7de54ab3e4 Document NAT hash, expiry, mapping holds and bounded transport ownership 2026-10-21 22:58:28 +02:00
evgeny 2c10272e15 Add repeatable NAT benchmarks for table size, payload size and full-pool misses 2026-10-21 22:55:24 +02:00
evgeny 55cc721c9b Test held NAT mappings under TUN congestion and reject invalid provider input 2026-10-21 22:54:24 +02:00
evgeny dea768c21a Hold outgoing NAT mappings through asynchronous TUN delivery 2026-10-21 22:52:19 +02:00
evgeny 824c663ebd Protect NAT mappings referenced by pending TUN transmissions 2026-10-21 22:51:25 +02:00
evgeny 80b481827c Verify bounded global NAT pressure and retained destination across mapping reuse 2026-10-21 22:46:09 +02:00
evgeny 8360e48622 Exercise NAT backpressure, mapping reuse, copy ownership and shutdown 2026-10-21 22:44:46 +02:00
evgeny 41a68b86bc Close NAT channels after cancelling producers and quiet transient TUN backpressure 2026-10-21 22:43:54 +02:00
evgeny cfc0051088 Test NAT boundary validation, hash collisions, expiry and allocation failures 2026-10-21 22:34:06 +02:00
evgeny cecc5d7d1f Validate provider replies before client TUN delivery 2026-10-21 22:32:29 +02:00
evgeny 5e2e6c15cf Preserve NAT index invariants across transport and reuse tests 2026-10-21 22:31:55 +02:00
evgeny d0c83cfff1 Add bounded NAT backpressure and forward TUN packets without copying 2026-10-21 22:30:01 +02:00
evgeny 9d6d6454b0 Reject malformed NAT configuration and use mapping lifecycle APIs in tests 2026-10-21 22:27:16 +02:00
evgeny 94fa3207f6 Index NAT mappings by hash and maintain free ports in constant time 2026-10-21 22:24:17 +02:00
evgeny 5a837f903c Validate NAT packet boundaries and distinguish skipped packets 2026-10-21 22:21:37 +02:00
evgeny 00b4b92749 Align NAT documentation with node ownership and router framing 2026-10-21 22:01:08 +02:00
evgeny 19a5870d5f Document NAT ownership, packet formats and API contracts 2026-10-21 22:00:06 +02:00
evgeny bfa23afae9 Restrict NAT delivery to its group and configured provider 2026-10-21 21:58:10 +02:00
evgeny 909005c1a4 Complete standalone NAT forward configuration fixture 2026-10-21 21:57:23 +02:00
evgeny ddc163a2b7 Cover NAT forward owners, full port range and invalid rules 2026-10-21 21:56:20 +02:00
evgeny ca471d777e Route static NAT forwards to explicit owners on all ports 2026-10-21 21:55:13 +02:00
evgeny 2c4f107e63 Require a target node for NAT port forward configuration 2026-10-21 21:54:41 +02:00
evgeny 3d0c4ff0a5 Isolate NAT mappings by source node identity 2026-10-21 21:53:17 +02:00
evgeny a9820bea42 Preserve IPv4 UDP checksum encoding through NAT 2026-10-21 21:51:49 +02:00
evgeny 52a73ea6a7 Correct incremental NAT checksum arithmetic 2026-10-21 21:50:59 +02:00
evgeny 6e9bacd843 Fix NAT flow lookup at the maximum port boundary 2026-10-21 21:48:28 +02:00
evgeny fbbd62acc4 Fix NAT packet ownership after router send failures 2026-10-21 21:43:00 +02:00
evgeny ef673eb3b7 Merge branch 'master' of http://git.syqiq.tech/jeka/utun2 2026-10-21 21:22:49 +02:00
evgeny 05b0927619 Fix TUN packet ownership, lifecycle and backend consistency
Unify TUN initialization and raw-IP writes, preserve socketpair directions, and bound reader delivery with queue backpressure. Make deferred packet ownership safe across close and uasync teardown, and apply per-interface MTU limits to lwIP MSS.

Validation: full check.sh passed 172 tests, 9 proxy integration checks, burst and load. TUN ASAN/UBSAN regressions passed 30 cases; TCP exchange passed with asymmetric and minimum MTUs. Sanitized NAT integration exposed an existing unaligned uint16_t read in eim_nat.c; that separate defect remains unchanged. Native Windows and FreeBSD validation remains outstanding.
2026-10-21 21:19:42 +02:00
evgeny e3f2feb480 Merge branch 'master' of http://git.syqiq.tech/jeka/utun2 2026-10-21 20:26:26 +02:00
evgeny a65b0c8786 Fix queue extraction in NTP regression cleanup 2026-10-21 20:18:49 +02:00
evgeny 6c84e680af Improve NTP failure diagnostics and source transition coverage 2026-10-21 20:18:17 +02:00
evgeny d6eed66926 Document NTP contracts and verify corrected wall time 2026-10-21 20:16:38 +02:00
evgeny 88bf65e07d Cover NTP correction, retries, faults and peer lifecycle 2026-10-21 20:15:17 +02:00
evgeny 13c1831baa Fix peer time cache ownership and callback teardown 2026-10-21 20:12:04 +02:00
evgeny 5609d57947 Fix NTP offset and bound asynchronous polling cycles 2026-10-21 20:11:04 +02:00
evgeny 488be0edd1 Record recurring attachment test timeout during control validation 2026-10-21 20:06:51 +02:00
evgeny e620567804 Finalize control server regression fixture cleanup 2026-10-21 20:04:30 +02:00
evgeny fdf2912427 Cover control server regressions and correct API documentation 2026-10-21 20:04:30 +02:00
evgeny 51922cd18e Fix control server buffer bounds and client resource ownership 2026-10-21 20:04:19 +02:00
evgeny 79946bb07c Keep firewall reload regression on the selective path 2026-10-21 20:00:28 +02:00
evgeny 41c32cf063 Set router packet length in firewall integration fixture 2026-10-21 19:59:34 +02:00
evgeny 4f627bddff Align firewall examples with symmetric destination filtering 2026-10-21 19:53:50 +02:00
evgeny 2a2a0ee267 Cover firewall parsing, bidirectional TUN filtering and reload failures 2026-10-21 19:52:51 +02:00
evgeny 5de0eb5115 Filter both directions of the main TUN and remove obsolete firewall guide 2026-10-21 19:49:32 +02:00
evgeny cf6c3c99e8 Reject invalid firewall configuration and preserve policy on reload failure 2026-10-21 19:48:54 +02:00
evgeny c3a7f77b54 Make firewall rule replacement atomic and validate IPv4 packets 2026-10-21 19:48:19 +02:00
evgeny 4f5651906c Report precise INI read failures and identity repair reasons 2026-10-21 19:09:03 +02:00
evgeny 2df21efc22 Bound edited INI growth and cover effective duplicate values 2026-10-21 19:06:59 +02:00
evgeny b0f5055c31 Describe shared INI parsing and distribute its internal header 2026-10-21 19:04:54 +02:00
evgeny 80eb331d6a Document config identity and publication guarantees 2026-10-21 19:04:53 +02:00
evgeny bb87a0845b Verify config updates preserve files and allocations under OOM 2026-10-21 19:03:39 +02:00
evgeny f7c8b95af6 Bound INI buffers to allocator limits and log allocation errors 2026-10-21 19:03:38 +02:00
evgeny 33130c1d74 Test identity preservation and failed config publication 2026-10-21 19:02:20 +02:00
evgeny f61c0c3e38 Preserve config identity and publish verified updates safely 2026-10-21 19:00:06 +02:00
evgeny 2410c39b71 Share INI parsing and validate complete configuration values 2026-10-21 18:54:43 +02:00
evgeny 5a57b59b50 Test emulator forwarding and partial initialization cleanup 2026-10-21 18:14:03 +02:00
evgeny ff3eb02bff Update emulator uasync lifecycle and document forwarding rules 2026-10-21 18:12:06 +02:00
evgeny 56d5fcd75a Test broadcast UUID lifetime and callback registration contracts 2026-10-21 18:10:43 +02:00
evgeny 484b620016 Preserve broadcast UUIDs until TTL and document callback contracts 2026-10-21 18:08:50 +02:00
evgeny 16f81575ce Consolidate TCP queue and resource lifecycle documentation in header 2026-10-21 17:59:08 +02:00
evgeny 10b039686c Consolidate queue usage and backpressure documentation in header 2026-10-21 17:57:34 +02:00
evgeny 194bf7bb45 Consolidate debug configuration documentation in header 2026-10-21 17:56:13 +02:00
evgeny a288afd8ce Consolidate socket lifecycle and wrapper documentation in header 2026-10-21 17:55:27 +02:00
evgeny 4f3f6d3e60 Consolidate platform adapter documentation in header 2026-10-21 17:55:27 +02:00
evgeny 1c4010ebed Consolidate serialization format and ownership documentation in header 2026-10-21 17:54:20 +02:00
evgeny ace9cb70d0 Consolidate timeout heap ownership and complexity documentation 2026-10-21 17:54:20 +02:00
evgeny af3c7a4217 Consolidate pool lifecycle and diagnostics documentation in header 2026-10-21 17:53:00 +02:00
evgeny e403a2f689 Consolidate memory ownership and allocation documentation in header 2026-10-21 17:53:00 +02:00
evgeny 3944459c29 Consolidate sliding minimum documentation in header 2026-10-21 17:52:02 +02:00
evgeny 48383ef95e Consolidate outgoing IP documentation in header 2026-10-21 17:52:02 +02:00
evgeny f020a6f62b Clarify CPU indicator polling and pending responses 2026-10-21 17:48:35 +02:00
evgeny d23a96a08e Document uasync scheduling, ownership and lifecycle contracts 2026-10-21 17:40:20 +02:00
evgeny dffcd19d21 Clarify queue callback scheduling and ownership contracts 2026-10-21 17:27:04 +02:00
evgeny 9079ab5c24 Fix debug timestamps, default output and log reopening 2026-10-21 17:10:44 +02:00
evgeny 7e39f16e0f Fix allocation size overflow, zero-size OOM and debug category parsing 2026-10-21 17:07:11 +02:00
evgeny 00819654cf Document POSIX descriptor zero exception in socket close 2026-10-21 16:57:44 +02:00
evgeny 346c06f31d Record TCP lifecycle validation and IPv6 selection caveat 2026-10-21 16:52:11 +02:00
evgeny ba7c2873c5 Initialize proxy timers before notifying connected owners 2026-10-21 16:48:25 +02:00
evgeny 0e15234ce1 Clarify TCP lifecycle and platform address selection contracts 2026-10-21 16:46:45 +02:00
evgeny e5fafacf99 Cover TCP timer replacement failures and pending FIN cleanup 2026-10-21 16:45:53 +02:00
evgeny d467d3aa8f Fix TCP connect timer ownership and pending FIN state 2026-10-21 16:44:19 +02:00
evgeny d5e489598d Clarify DNS lifetimes and parser and video plane limits 2026-10-21 16:33:16 +02:00
evgeny 1ff02188ca Fix Silero model cleanup and document runtime configuration 2026-10-21 16:29:44 +02:00
evgeny f31b34d0f0 Clarify serialization limits, cleanup and error codes 2026-10-21 16:18:51 +02:00
evgeny ecd5b9fc9d Clarify memory pool counters and strbuf error documentation 2026-10-21 16:14:48 +02:00
evgeny aca6364378 Correct call routing, media channels and API documentation 2026-10-21 16:11:36 +02:00
evgeny 88e930cc0a docs: correct member file protocol and media download contracts 2026-10-21 16:01:30 +02:00
evgeny be235e01aa docs: correct DM payload, history and transfer cancellation contracts 2026-10-21 15:53:28 +02:00
evgeny 66f004f725 docs: describe actual DM identity derivation and crypto modules 2026-10-21 15:52:45 +02:00
evgeny cbe22899c2 docs: align chat invite and member sync descriptions with code 2026-10-21 15:47:56 +02:00
evgeny df36e504fc docs: remove completed and obsolete project tasks 2026-10-21 15:47:30 +02:00
evgeny 7c814f5cb9 Route desktop codec diagnostics through the shared log
Quiet capability probes, preserve runtime errors, and register the desktop portal application. Add logging and desktop launcher regression coverage.
2026-10-21 15:45:40 +02:00
evgeny 9ba78c084b docs: correct topology API and router timeout descriptions 2026-10-21 15:40:56 +02:00
evgeny d644126cac docs: align ETCP handshake and epoch descriptions with code 2026-10-21 15:37:01 +02:00
evgeny f59f64ea48 docs: remove reviewed header backup files 2026-10-21 15:22:42 +02:00
evgeny f5f106c682 docs: clarify header APIs and preserve originals in .h1 2026-10-21 15:21:27 +02:00
evgeny abf342534f Encrypt P2P call media and validate service IDs
Require signed and encrypted call audio/video using static identity keys. Fix attachment service ID collisions and media download handle lifetime; isolate LAN tests and audit the shared service registry.
2026-10-21 15:06:27 +02:00
evgeny 8e46cf9254 docs: refresh project file descriptions in AGENTS.md 2026-10-21 14:54:06 +02:00
evgeny 15b037aef7 Scroll to latest chat messages with End key 2026-10-21 13:31:50 +02:00
evgeny 69e534304b Darken desktop chat backgrounds and lighter panels 2026-10-21 13:26:05 +02:00
evgeny 4dbc543cd3 Increase contrast of chat scrollbar thumb only 2026-10-21 13:21:30 +02:00
evgeny 4f6808156f Add chat history keyboard scrolling and remove unused PTT setting 2026-10-21 13:05:31 +02:00
evgeny 5870efdf04 Default stream redundancy to zero on Android and desktop 2026-10-21 12:42:23 +02:00
evgeny 34db81c5cf Show green stream watch buttons only for active streams 2026-10-21 12:30:08 +02:00
evgeny a31436e421 Expand chat README and add stream image 2026-10-21 02:31:00 +02:00
evgeny 550f384c69 Tidy stream video worker source formatting 2026-10-21 01:40:04 +02:00
evgeny a6b909b70e Add device regression for independent stream audio and video workers 2026-10-21 01:38:50 +02:00
evgeny fcb0768052 Protect SoundTouch lookahead when catching up live stream audio 2026-10-21 01:38:50 +02:00
evgeny 5d9da0c6b1 Preserve exact source EOF across tempo changes and expose DSP lookahead 2026-10-21 01:38:50 +02:00
evgeny e8ee608ba9 Document independent audio preparation and live stream catchup 2026-10-21 01:28:20 +02:00
evgeny 4e5530aca0 Isolate Android live video decoding from audio preparation 2026-10-21 01:23:35 +02:00
evgeny 4fa3b18cc2 Feed Android stream mixer from prepared PCM without holding DSP lock 2026-10-21 01:18:56 +02:00
evgeny 50cf61e9cd Mix partial stream PCM without copying stale buffer tails 2026-10-21 01:11:35 +02:00
evgeny c6ed01110e Exercise audio continuity during video stalls and generation changes 2026-10-21 01:03:19 +02:00
evgeny 1764603977 Isolate live video decoding from audio preparation in ChatGUI 2026-10-21 01:00:31 +02:00
evgeny 6c619d5f2a Recover stream playback stalls with bounded proportional catchup 2026-10-21 00:56:47 +02:00
evgeny 58c0fc6bba Separate stream audio DSP from bounded PCM consumption 2026-10-21 00:54:30 +02:00
evgeny 32e648ea9e Release audio holds at video EOF and stop Android batches promptly 2026-10-21 00:15:34 +02:00
evgeny b2efab9806 Document per-track completion and Android batch wakeups 2026-10-21 00:13:01 +02:00
evgeny a342316e7a Verify delayed decoders with unequal audio and video tails 2026-10-21 00:13:01 +02:00
evgeny c887780022 Consume Android batches with independent track completion 2026-10-21 00:13:01 +02:00
evgeny a538f99bf0 Expose viewer wake signals and complete audio independently on Android 2026-10-21 00:13:01 +02:00
evgeny 9fb4823df0 Batch Android viewer records and wake readers on data or stop 2026-10-21 00:13:01 +02:00
evgeny a2fb562a22 Drain desktop tracks independently and cancel obsolete media on reset 2026-10-20 23:54:55 +02:00
evgeny 852c05590d Expose track completion to desktop and retain the longer media tail 2026-10-20 23:53:58 +02:00
evgeny a54031081b Deliver independent track ends and invalidate batches on gaps 2026-10-20 23:53:23 +02:00
evgeny 23c4e4efbc Diagnose delayed decoder completion with buffered audio 2026-10-20 23:46:59 +02:00
evgeny 5bc0c1ece4 Document bounded desktop stream batches and worker wakeups 2026-10-20 23:42:28 +02:00
evgeny fbab6eae5d Anchor batch regression at a single initial keyframe 2026-10-20 23:41:12 +02:00
evgeny 0d9c728efe Test bounded batches, track budgets, notifications and FIN 2026-10-20 23:34:57 +02:00
evgeny 039c4a9ed4 Consume desktop media batches with per-track backpressure and wakeups 2026-10-20 23:31:50 +02:00
evgeny 179f248db8 Deliver bounded media batches to desktop consumers 2026-10-20 23:30:10 +02:00
evgeny 589cdcc81f Add bounded viewer batches and readiness notifications 2026-10-20 23:29:23 +02:00
evgeny 6997a82af1 Enable publisher timing logs in diagnostic test runs 2026-10-20 22:32:33 +02:00
evgeny c6f7d50838 Measure stream viewer request and worker delays 2026-10-20 22:30:04 +02:00
evgeny 7ce60ca0f2 Trace desktop stream stalls across playback and preview UI 2026-10-20 22:20:31 +02:00
evgeny b1112981fa Timestamp Android decoder output at the observation point 2026-10-20 21:44:10 +02:00
evgeny a4419b4c89 Validate Android surface timestamps in stream diagnostics 2026-10-20 21:40:20 +02:00
evgeny 1b036e4ea9 Trace stream startup decoding and presentation delays 2026-10-20 21:34:24 +02:00
evgeny f38aa3b08d Log stream startup key age and buffer handoff delays 2026-10-20 21:27:51 +02:00
1812 changed files with 230387 additions and 46953 deletions

No files matched your search

+3
View File
@@ -4,6 +4,7 @@ build-win/
tools/chatgui/build/
tools/chatgui/rlottie_build/
tools/chatgui/ffmpeg/ffmpeg_build/
tools/chatgui/qt_multimedia/build/
tools/lightsout/build/
# Build outputs
@@ -77,6 +78,8 @@ callgrind.out.*
tests/*.log
tests/*.trs
tests/logs/
/db_a/
/db_b/
# Mass update logs
logs/
+173 -35
View File
@@ -299,6 +299,9 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
│ ├── dm/ # Личные сообщения, E2E-вложения и offline-mailbox
│ ├── call/ # Звонки и общий голосовой стек
│ ├── radio/ # Групповая PTT-рация
│ ├── stream/ # Прямые трансляции: подписанные RS-блоки, выбор поставщиков, аудио/видео
│ ├── member_files/ # Файловое хранилище участников CHAT-группы и асинхронные передачи
│ ├── local_transport/ # Обнаружение устройств и доставка приглашений в локальной сети по UDP
│ ├── proxy/ # SOCKS5, TCP/UDP/ICMP прокси
│ ├── lwip_tcp/ # Встроенный lwIP TCP стек
│ ├── media_delivery/ # Блоки медиа каналов и передача неизменяемых файлов
@@ -336,13 +339,13 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `tun_linux.c` `tun_freebsd.c` `tun_windows.c` - Platform-specific TUN implementations
- `tun_route.c/h` - TUN routing table sync
- `config_parser.c/h` - INI-style config file parsing
- `config_updater.c/h` - Config file modification utilities
- `config_updater.c/h` - Проверка и сохранение согласованных X25519-ключей и node_id в INI-конфиге
- `control_server.c/h` - Control/monitoring server (etcpmon backend API)
- `firewall.c/h` - Firewall rules (per-interface filtering)
- `eim_nat.c/h` - Endpoint-Independent Mapping NAT engine
- `nat_transport.c/h` - NAT transport layer (packet relay)
- `ntp_time.c/h` - NTP time synchronization
- `ntp_node_time.c/h` - Inter-node time synchronization
- `nat_transport.c/h` - Передача IPv4 между отдельным TUN и удалённым NAT-провайдером через UTUN-router; локальный провайдер использует eim_nat
- `ntp_time.c/h` - Асинхронная NTP-синхронизация: поправка времени instance без изменения часов ОС
- `ntp_node_time.c/h` - Получение временной поправки от синхронизированных ETCP-пиров и диагностика расхождения часов
- `broadcast.c/h` - Широковещательная рассылка данных по topo-группе (UUID-дедупликация, TTL)
- `video/video.c/h` - Пробинг и транскодирование видео (FFmpeg, опционально; H.264/MP4 ≤720p)
- `dnsmasq/` - Архив dnsmasq-2.93.tar.xz для встроенной сборки
@@ -353,47 +356,54 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `etcp_connections.c/h` - Socket and link management, INIT handshake, keepalive, PING/PONG
- `etcp_session.c/h` - Согласование эпох ETCP-сессии через HELLO/CHALLENGE/CONFIRM и проверка принадлежности DATA сессии
- `etcp_loadbalancer.c/h` - Multi-link load balancing with traffic shaper
- `etcp_debug.c/h` - ETCP packet dump/formatting
- `etcp_debug.c/h` - Диагностический разбор секций ETCP_DGRAM и форматирование IPv4-адресов
- `etcp_dump.c/h` - ETCP дамп/декодирование пакетов
- `etcp_bbr.c/h` - BBR congestion control for ETCP
- `etcp_connect.c/h` - ETCP outbound connections
- `etcp_keepalive.c/h` - Keepalive-пакеты, адаптивный период, смена режима standby/normal (мобильные узлы)
- `auto_socket.c/h` - Автосоздание UDP+TCP сокетов на всех интерфейсах и линков к ETCP-соединениям (`auto_sockets=yes`)
- `pkt_normalizer.c/h` - Packet fragmentation/reassembly (packer/unpacker)
- `packet_dump.c/h` - Packet hex dump utility
- `dummynet.c/h` - Network emulator integrated into utun (for testing)
- `secure_channel.c/h` - AES-CCM encryption with X25519 key exchange, pubkey obfuscation
- `packet_dump.c/h` - Текстовая сводка IPv4-пакета: адреса, поля транспорта и короткий hex-фрагмент
- `dummynet.c/h` - Двунаправленный UDP-эмулятор между заданными endpoint: задержка, ограничение скорости и случайные потери
- `secure_channel.c/h` - X25519, пакетное AES-128-CCM, потоковое AES-CTR, подписи Ed25519 и обфускация публичного ключа
- `etcp_padding.c/h` - Выбор длины случайного padding и периодическое обновление диапазона для instance/соединения
- `etcp_tx_stats.c/h` - Общая статистика исходящих очередей, inflight и подтверждённых за секунду байтов ядра
- `crc32.c/h` - CRC32 checksums
- `stcp.c/h` - STCP протокол (Secure TCP)
- `stcp_server.c/h` - STCP сервер
- `stcp_client.c/h` - STCP клиент
- `stcp_link.c/h` - STCP линк-уровень
- `stcp.c/h` - Зашифрованные кадры поверх TCP: согласование ключей/эпох, AES-CTR, CRC, очереди и закрытие соединения
- `stcp_server.c/h` - Приём входящих STCP-соединений, handshake и передача готового соединения владельцу
- `stcp_client.c/h` - Исходящее STCP-подключение, в том числе через SOCKS5 и REALITY
- `stcp_link.c/h` - Подключение STCP к ETCP_LINK: передача пакетов, backpressure и жизненный цикл TCP-линка
- `socks_client.c/h` - Исходящий SOCKS5-транспорт: TCP CONNECT и UDP ASSOCIATE с переподключением control-сокета
- `node_conn_direct.c/h` - Общий прямой транспорт к пиру с отдельным handle каждого владельца; обновление линков по адресам узла
- `socket_monitor.c/h` - Socket state monitoring
- `socket_monitor.c/h` - Наблюдение за адресами интерфейсов и маршрутами ОС, обновление сетевого состояния ETCP-сокетов
- `reality.c/h` - REALITY-style TLS ClientHello/ServerHello камуфляж для STCP
- `reality_fingerprint.c/h` - Статические отпечатки (cipher suites, groups, ALPN) для REALITY-камуфляжа
- `reality_io.c/h` - Внешний REALITY-handshake и поток защищённых записей STCP, Finished, replay-защита и выбор relay
- `reality_record.c/h` - TLS-подобные AES-128-GCM записи: вывод ключей, счётчики направлений, padding и KeyUpdate
- `reality_relay.c/h` - Релей неавторизованных клиентов на реальный HTTPS-сайт
- `stun_nat.c/h` - Проверка mapping/filtering NAT через внешние STUN-серверы, RFC 5780 и кеш результатов по IP/интерфейсу
- `call_ring.c/h` - Кольцевой трейс контрольных точек освобождения ETCP/STCP-ресурсов для диагностики teardown/UAF
**BBR (src/transport_layer/BBR/)**
- `bbr_v3.c` - BBR congestion control algorithm v3
**Routing Layer (src/routing_layer/)**
- `routing.c/h` - Routing table (local)
- `route_lib.c/h` - Routing library
- `route6_lib.c/h` - IPv6 routing
- `routing.c/h` - Обмен IPv4-пакетами UTUN между локальным TUN и сервисом DATA ETCP-router
- `route_lib.c/h` - Локальная таблица IPv4-подсетей UTUN: добавление/удаление маршрутов и поиск узла назначения
- `route6_lib.c/h` - Локальная таблица IPv6-подсетей на radix tree с поиском по самому длинному префиксу
- `route_ping.c/h` - Пинг цели через явно выбранного BGP-посредника для NAT-проверки
- `route_connectivity.c/h` - Route connectivity checks
- `route_connectivity.c/h` - Прямые UDP/TCP-пробы адресов узла для оценки достижимости и RTT при выборе пиров
- `topo_group.c/h` - Сессии UTUN/CHAT (JOIN/ACCEPT, эпохи, READY), групповые запросы, NODEINFO/WITHDRAW и владение NCD
- `topo_group_connect.c/h` - Подбор пиров CHAT-группы по роли: суперузлы → desktop → mobile; история/RTT внутри класса, backoff и standby burst
- `topo_group_invite.c/h` - Получение описания канала через INVITE_INFO_REQ/RESP; добавление мембера реализовано в chat_join/chat_sync
- `topo_node.c/h` - Node management (модель узла: TOPO_NODE/TOPO_GROUP_NODE, сериализация, node_registry)
- `topo_node_sqlite.c/h` - SQLite persistence for nodes
- `topo_node.c/h` - Модель TOPO_NODE/TOPO_GROUP_NODE, подписанные снимки узлов, сериализация и общий node_registry
- `topo_node_sqlite.c/h` - Хранение подписанных снимков узлов, адресов, каналов и блоков мемберов в общей SQLite
- `topo_recovery.c/h` - Восстановление потерянных маршрутов группы через READY-сессии, отмена попыток при stop
- `conn_mgr.h` + `conn_mgr_core.c`/`conn_mgr_indirect.c`/`conn_mgr_monitor.c` + `conn_mgr_priv.h` — Connection Manager (handle-based API, 3-phase DIR/REV/IND)
- `etcp_router.c/h` - ETCP router/multiplexer (мультиплексирование каналов, transit forwarding)
- `nat_detection.c/h` - NAT type detection
- `etcp_router.c/h` - Надёжные логические каналы сервисов поверх BGP-маршрутов: ACK, окна, транзит и защита от циклов
- `route_tx_stats.c/h` - Скользящее окно подтверждённых payload-байтов логического канала для оценки скорости доставки
- `multicast.c/h` - Рассылка списку узлов группы с разделением маршрута на ветви, локальными подписками и отчётами о потерях
- `nat_detection.c/h` - Проверка mapping и доступности входящих рабочих сокетов через ETCP-пиров с учётом предварительных STUN-измерений
- `address_profile.h` - Профиль endpoint: изменение адреса, доступность входящих и источник измерения ETCP/STUN
- `sock_match.c/h` - Классификация локальных сокетов и адресов пира, отбор совместимых пар для прямого подключения
- `route_crypto.c/h` - Пред/пост-обработка SVC_ROUTE пакетов (encrypt-then-sign)
@@ -408,9 +418,15 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `member_sync.c/h` - Синхронизация участников каналов поверх merkle_sync. Два подписанных блока (мембер/владелец), по-блочное сравнение версий, верификация подписей. Удаление — только битая запись
- `merkle_sync.c/h` - Универсальный движок синхронизации на Merkle-деревьях (5 уровней × 32 бакета, SHA256). Пиры обмениваются хешами и передают только различия; per-session out-очередь с backpressure. Не привязан к конкретному типу данных (коллбэки `data_ops`)
- `merkle_tree.c/h` - Производный индекс Merkle-хешей в SQLite; восстанавливается из данных модели, обновляется с ними в одной транзакции
- `chat_profile.c` - Собственный профиль: имя узла, сетевые адреса, сохранение UI-состояния (часть chat_core)
- `chat_profile.c` - Подписанный профиль мембера: имя, аватар и опции сервисов; локальное UI-состояние (часть chat_core)
- `chat_channel.c` - Создание и настройка каналов: таблицы, криптоключи, CHAT-группа и планировщик подключения (часть chat_core)
- `chat_msg.c` - Отправка и приём сообщений: запись в локальную БД, автоматическая рассылка всем участникам канала (часть chat_core)
- `chat_feedback.c/h` - Подписанные реакции и ответы: версии состояния, сохранение отмен и Merkle-синхронизация между участниками
- `chat_poll.c/h` - Создание опросов, голосование, реакции и JSON-снимки результатов для UI/headless
- `chat_poll_codec.c` - Проверка и wire-кодеки опросов, ответов и реакций; общий каталог эмодзи (API в chat_poll.h)
- `chat_attachment.c/h` - Зашифрованные вложения канала: ключи, запросы доступа, ручное одобрение автора и сохраняемый outbox
- `chat_local.c/h` - Обнаружение устройств чата и обмен готовыми invite-ссылками через локальный UDP-транспорт
- `group_avatar.c/h` - Подписанная аватарка канала: хранение версии в SQLite, проверка подписи и передача блоков через router
- `chat_status.c` - Сбор диагностики: текущее время, активные соединения, типы NAT. Отправляется в GUI (часть chat_core)
- `chat_member.c/h` - Единая структура мембера для отображения в GUI (десктоп/headless/Android), фиксированная сериализация на проводе
- `chat_admin.c/h` - Передача канального приватного ключа (прав админа) другому узлу
@@ -422,7 +438,8 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
**Личные сообщения (src/dm/)**
- `dm_core.c/h` - Беседы двух узлов, подписанные E2E-сообщения, SQLite/outbox, доставка через router/mailbox и квитанции
- `dm_crypto.c/h` - Вывод ID беседы и ключа X25519, AES-256-CCM сообщений и потоковое шифрование/проверка медиа
- `dm_crypto.c/h` - Вывод ID беседы и ключа X25519, AES-256-CCM сообщений и E2E-контейнеры медиа через media_crypto
- `dm_history.c/h` - Локальное удаление истории и скрытие бесед; поколения задач и отпечатки удалённых сообщений против повторов
- `dm_mailbox.c/h` - Offline-очередь суперузла: хранение подписанных сообщений и повтор доставки до квитанции получателя
- `dm_media.c/h` - Подготовка, доставка и публикация E2E-вложений; ciphertext-хранилище и отдельные квитанции файлов
- `dm_media_priv.h` - Внутренние SQL/control-операции для dm_media и dm_mailbox_media
@@ -430,11 +447,25 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
**Звонки (src/call/)**
- `call.c/h` - Сигналинг и медиа P2P-звонка через ETCP-router, состояния звонка и оптимизация пути через conn_mgr
- `call_proto.h` - Wire-формат сигналинга и медиа, треки/кодеки, причины завершения
- `call.c/h` - P2P аудио/видеозвонок: подписанный E2E-сигналинг, состояния, политика занятости и оптимизация пути через conn_mgr
- `call_priv.h` - Общее внутреннее состояние сессии для call.c и call_video_transport.c; доступ только из uasync
- `call_proto.h` - Wire-формат сигналинга, аудиокадров и управления видеотреком; треки/кодеки и причины завершения
- `call_audio.c/h` - Общий аудио-движок: кодирование/декодирование Opus, jitter-буфер и тоны, API feed/pull PCM
- `call_jitter.cpp/h` - FIFO кодированных Opus-кадров, адаптивный запас и SoundTouch time-stretch при воспроизведении
- `call_jitter.cpp/h` - FIFO Opus, адаптивный сетевой запас, декодирование на pull и восстановление воспроизведения после пауз
- `call_jitter_window.h` - Окно из десяти секундных интервалов для оценки глубины очереди и изменения задержки доставки
- `call_clock.h` - Метки времени захвата и снимок реально проигранного аудио для синхронизации видеотрека
- `call_delay.cpp/h` - Уменьшение накопленной задержки PCM прямым ускорением и SoundTouch с сохранением исходной шкалы времени
- `call_timeline.cpp/h` - Карта исходного PTS через обработку SoundTouch до позиции аудиоустройства
- `call_video.c/h` - Общий формат H.264/H.265 видеотрека, согласование возможностей и сборка кадров из фрагментов
- `call_video_bitstream.c/h` - Проверка конфигурации и IDR без reorder, профиля/уровня и геометрии H.264/H.265; KEY-пробы кодеков
- `call_video_transport.c/h` - Отдельные router-каналы control/audio/video, backpressure, привязка видео к аудио и запросы KEY
- `call_video_rate.c/h` - Регулятор битрейта и допуска новых видеокадров по скорости доставки, RTT и долгу очереди
- `call_video_port.c/h` - Потокобезопасный обмен кадрами и командами между платформенными video workers и uasync-транспортом
- `call_video_playout.c/h` - Расписание показа по аудиочасам, ожидание/отбрасывание кадров и подтверждение фактического показа
- `call_video_fixtures.h` - Встроенные H.264/H.265 KEY-пробы для проверки базовых режимов кодека
- `call_video_fast_fixtures.h` - KEY-пробы видеорежимов с частотой 60 fps
- `call_video_fullhd_fixtures.h` - KEY-пробы видеорежимов Full HD
- `call_video_portrait_fixtures.h` - KEY-пробы видеорежимов в портретной ориентации
- `call_tones.c/h` - Генерация PCM-тонов паузы и завершения звонка
- `call_headless.c/h` - Отдельный TCP-аудиосокет headless-клиента: обмен PCM; сигналинг остаётся на control-сокете
@@ -445,14 +476,17 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `radio_audio.c/h` - Общий аудио-движок: независимые RX/TX, Opus, микширование источников, ручной PTT и VAD-автомат
- `radio_jitter.cpp/h` - Буфер кодированных кадров каждого источника с pre-roll и SoundTouch time-stretch на pull
- `radio_vad.h` - Ресемплинг 48→16 кГц и автомат авто-PTT с подтверждением речи, задержкой завершения и учётом занятого канала
- `radio_auto.h` - Общий автомат автопередачи по VAD/уровню звука, без захвата аудио и сетевого I/O
- `radio_call.c/h` - Адресное приглашение участника в рацию канала: сигналинг вызова, занятость, принятие и отмена
- `radio_headless.c/h` - TCP-аудиосокет headless-рации: PCM и команды начала/конца PTT
**Прокси (src/proxy/)**
- `proxy_protocol.h` - Общий TCP-протокол и управление потоком: CONNECTED, DATA, кредит WINDOW, упорядоченный FIN
- `socks_proxy.c/h` - Клиентские SOCKS5 CONNECT и HTTP proxy/CONNECT, DNS и передача потока выбранному exit-узлу
- `udp_proxy.c/h` - UDP прокси
- `icmp_proxy.c/h` - ICMP прокси
- `http_proxy.c/h` - Потоковый HTTP/1.x кодек: проверка заголовков, разбор тела/chunked и учёт потреблённых байтов для WINDOW
- `udp_proxy.c/h` - Передача UDP из TUN через exit-узел, сопоставление ответов и удаление неактивных потоков
- `icmp_proxy.c/h` - Проксирование IPv4 ICMP echo через raw socket exit-узла с восстановлением исходных id/seq
- `tcp_proxy_server.c/h` - Exit-сторона TCP-прокси: реальные исходящие сокеты, потоки по (peer, stream_id), окна и half-close
- `tcp_proxy_client.c/h` - Клиентская сторона TCP-прокси: адаптер TUN/lwIP и обмен с настроенным exit через ETCP-router
@@ -474,6 +508,45 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `attachment.c/h` - Общие метаданные file/voice/video, проверка и компактная wire-сериализация
- `voice_file.c/h` - Worker-кодирование PCM в контейнер Opus с длительностью и waveform для desktop/Android
- `attachment_send.c/h` - Асинхронная подготовка голоса/видео и отправка в зафиксированный канал или DM
- `media_crypto.c/h` - Общие AES-256-CCM примитивы и порционное шифрование/проверка файлов для DM и групповых вложений
- `encrypted_file.c/h` - Контейнер группового вложения: шифрование метаданных/файла, проверка SHA256 и durable-публикация результата
**Трансляции (src/stream/)** — live-аудио/видео CHAT-группы с подписью источника, Reed–Solomon и раздачей через участников.
- `stream.c/h` - Жизненный цикл трансляции, локальные handles издателя/читателей, события и публикация подписок
- `stream_priv.h` - Внутренний доступ к сессиям, приём проверенных DATA/END и взаимодействие с планировщиком relay
- `stream_proto.h` - Форматы подписанной пачки и RS-частей, дескриптор источника, размеры и коды результата
- `stream_block.c/h` - Подпись пачки Ed25519 до RS-кодирования, разбор частей и проверка восстановленных данных
- `stream_buffer.c/h` - Ограниченное кольцо RS-частей: дедупликация, восстановление пачек, проверка подписи и вытеснение старых данных
- `stream_source.c/h` - Упаковка исходных байтов в подписанные RS-пачки, сброс неполной пачки по таймеру и завершение источника
- `stream_member.c/h` - Объявления источников и подписок в опциях подписанного мембера; разбор и проверка принадлежности источника
- `stream_wire.c/h` - Протокол выдач и relay: кодограммы управления, пути, метрики и подписанное завершение END
- `stream_network.c/h` - Выдача блоков через прямой ETCP, NCD-владение, управляющие очереди, аренда подписок и reverse-запросы
- `stream_optimizer.c/h` - Автоматический выбор и перенос поставщиков субпотоков, пробы доступности и привлечение relay
- `stream_metrics.c/h` - Оценка относительного отставания субпотока и истории проблем по часам источника без NTP
- `stream_load.c/h` - Учёт логической очереди DATA и её роста для обнаружения перегрузки раздающего узла
- `stream_media.c/h` - Формат uAV2: упаковка/проверка видеокадров, конфигурации кодека, PTS и Opus внутри FEC-пачек
- `stream_media_buffer.c/h` - Медиаиндекс общего RS-кольца и независимые курсоры audio/video; сборка кадров и восстановление с KEY
- `stream_publisher.c/h` - Общий потокобезопасный publisher desktop/Android: очередь готовых кадров, публикация и завершение с FIN
- `stream_viewer.c/h` - Независимые viewers: запрос ограниченных батчей по бюджетам треков, уведомления готовности и конца audio/video
- `stream_playback_audio.cpp/h` - Opus/SoundTouch и очередь готового PCM; ускорение без изменения высоты и привязка к позиции устройства
- `stream_playback_clock.c/h` - Общие часы воспроизведения и плавный догон live-потока по непрерывному запасу готового материала
**Файлы участников (src/member_files/)**
- `member_files.c/h` - Сервер и асинхронный клиент хранилища CHAT-группы: права доступа, запросы и события через защищённый router
- `protocol.c/h` - Wire-кодек файловых команд, снимки версий каталогов/файлов и токены временных загрузок
- `storage.c/h` - Серверные каталоги участников, квоты, файловые операции, временные загрузки и их очистка
- `transfer.c` - Передача файлов с CM handle, backpressure, дисковым worker, проверкой хеша и публикацией результата
- `disk.c/h` - Дисковые примитивы POSIX/Windows: безопасное разрешение путей без ссылок и I/O по 64-битному смещению
- `worker.c/h` - Единственный дисковый pthread с ограниченной очередью и возвратом результатов в uasync
- `private.h` - Внутреннее состояние запросов, передач, серверного хранилища и дискового worker
**Локальная сеть (src/local_transport/)**
- `local_transport.c/h` - Открытый UDP-транспорт LAN: обнаружение устройств, доставка сообщений с ACK/повторами и ограничения входящего потока
- `platform.c/h` - Снимок IPv4/IPv6 интерфейсов, broadcast/multicast-адреса, приём метаданных UDP и проверка локальности источника
- `protocol.h` - Wire-формат объявлений, сообщений и ACK: ID/эпохи устройств, ID запроса и проверка UTF-8 имени
**Libraries (lib/)**
- `u_async.c/h` - Async event loop (epoll/poll/select, timers via timeout_heap)
@@ -484,6 +557,7 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `mem.c/h` - Memory wrappers with leak tracking (`u_malloc`/`u_free`/`u_calloc`/`u_strdup`)
- `serialize.c/h` - Binary serialization utilities
- `reed_solomon.c/h` - Кодирование и восстановление пачки данных Рида—Соломона с настраиваемым числом субблоков и избыточностью
- `video_plane.c/h` - Копирование YUV-плоскости с поворотом 0/90/180/270°, учётом stride и проверкой границ без выделения памяти
- `swm_min.c/h` - Sliding window minimum (for RTT min tracking)
- `getmyip.c/h` - Локальный IP, который ОС выберет для UDP к заданному адресу (bind/connect/getsockname)
- `myip.c` - My IP helper (no header)
@@ -509,6 +583,16 @@ UASYNC/LL_QUEUE/MEMORY/TIMING объединены в SYS, NORMALIZER/BBR — в
- `soundtouch-master/` - SoundTouch: изменение темпа аудио в jitter-буферах звонка и рации
- `wintun.h` - Wintun API header for Windows TUN driver
**Проверки (tests/)**
- `Makefile.am` - Состав тестовых целей, зависимости и отдельные проверки runner, service IDs и скрипта сборки
- `run_tests.py` - Запуск тестов ограниченным пулом с отдельными логами и последовательными барьерами для CPU/LAN-проверок
- `test_run_tests.py` - Проверки пула runner, эксклюзивного запуска, обработки ошибок и сигналов
- `test_service_ids.py` - Проверка уникальности ID транспортных и router-сервисов
- `test_build_script.py` - Регрессии выбора платформы, конфигурации и инкрементальной работы build.sh
- `stream_netns/` - Linux network namespaces: топологии, NAT/STUN-сценарии и проверка трансляций в изолированной сети
- `local_transport_ipv6.sh` - Проверка IPv6 link-local обнаружения и доставки в изолированной локальной сети
**Memory Pools in UTUN_INSTANCE:**
- `data_pool` — для данных пакетов (payload), используется input_queue/output_queue фрагментами
- `pkt_pool` — для struct ETCP_DGRAM (сетевые пакеты на отправку/приём)
@@ -685,11 +769,18 @@ cmake .. && make -j4
| Файл | Назначение |
|------|-----------|
| `main.cpp` | Точка входа, инициализация QApplication |
| `mainwindow.h/cpp` | Главное окно, списки каналов/DM/участников, сообщения, трей, события ядра и окна звонков |
| `chatview.h/cpp` | QListView с фоновым изображением, hover-сигнал, drag-to-select |
| `main.cpp` | Точка входа, QApplication, язык интерфейса и запуск единственного экземпляра профиля |
| `single_instance.h/cpp` | Блокировка каталога профиля и передача запроса показа окна уже работающему экземпляру |
| `gui_language.h` | Выбор языка интерфейса независимо от регионального формата дат и чисел |
| `mainwindow.h/cpp` | Главное окно, каналы/DM, трей, события ядра, звонки, локальные приглашения и окна трансляций |
| `chatview.h/cpp` | Список сообщений: фон, hover, выделение текста и прокрутка истории мышью/клавиатурой |
| `messagelist.h/cpp` | Модель сообщений из БД, обновления доставки/медиа, анимации, состояние просмотра канала |
| `messagedelegate.h/cpp` | QStyledItemDelegate: бабблы, текст, цитаты, реакции, оверлей анимаций |
| `messagefeedback.cpp` | Действия MessageList: создание опроса, голосование, выбор реакции и показ результатов |
| `attachment_key_ui.cpp` | Список запросов на расшифровку групповых вложений и решения автора о выдаче ключа |
| `message_links.h/cpp` | Разбор границ utun:// и HTTP/HTTPS ссылок для подсветки и обработки нажатий в сообщении |
| `message_notification.h/cpp` | Уведомление о сообщении без захвата фокуса, переход в беседу и скрытие после активности пользователя |
| `user_activity_monitor.h/cpp` | Ожидание первой активности через системный idle time либо события приложения |
| `emoji.h/cpp` | EmojiData/EmojiCategory/EmojiType, 4 категории, `g_animatedEmojiMap` |
| `emojipanel.h/cpp` | Эмодзи-пикер: QTabWidget + QGridLayout, EmojiButton с hover-анимацией |
| `emojitabbar.h/cpp` | Кастомный QTabBar для эмодзи-панели |
@@ -705,11 +796,13 @@ cmake .. && make -j4
| `invitedialog.h/cpp` | Диалог приглашения пользователя |
| `invite_link.h/cpp` | Логика invite-ссылок |
| `inviteby.h/cpp` | Диалог приглашения по invite-ссылке (отправка через узел) |
| `dminvitedialog.h/cpp` | Выбор канала для приглашения собеседника из DM с сопоставлением результата по request_id |
| `settingsdialog.h/cpp` | Окно настроек |
| `creategroupdialog.h/cpp` | Диалог создания группы |
| `channelsettingsdialog.h/cpp` | Диалог настроек канала |
| `renamedialog.h/cpp` | Диалог переименования |
| `networksettingspage.h/cpp` | Страница сетевых настроек |
| `addressprofiletext.h` | Читаемое представление mapping, доступности входящих и источника NAT-измерения |
| `nodespage.h/cpp` | Таблица узлов + дамп в настройках |
| `statuspage.h/cpp` | Страница статуса (NTP + соединения + живые часы) |
| `databasesettingspage.h/cpp` | Страница обслуживания БД в настройках |
@@ -718,24 +811,52 @@ cmake .. && make -j4
| `audiodevicesettingspage.h/cpp` | Страница настроек аудиоустройств |
| `sound_manager.h/cpp` | Общий miniaudio-контекст, уведомления/PCM, микширование голоса, маршруты устройств и восстановление |
| `audio_device.h/cpp` | Жизненный цикл miniaudio-устройства, прогресс callbacks, пауза и повтор запуска после сбоя |
| `audio_buffer_tuning.h` | Подбор размера аппаратного аудиобуфера по повторным XRUN с сохранением настройки при reopen |
| `audio_capture.h/cpp` | Совместное использование одного микрофона трансляцией и рацией, подписки PCM и смена профиля захвата |
| `audio_capture_lease.h` | Владение захватом, исключающее одновременную работу publisher, звонка и записи голосового сообщения |
| `audio_event_queue.h` | Ограниченная очередь PCM/команд с несколькими producers и резервом для управляющих событий |
| `audio_frame_ring.h` | Предвыделенное SPSC-кольцо кадров переменной длины под mutex; при переполнении удаляет старейший |
| `voice_audio_io.h/cpp` | Workers захвата/AEC и воспроизведения; упорядочивание PCM/PTT/mute и итоговый render-reference |
| `voice_capture_clock.h` | Непрерывные PTS захваченного PCM по позиции сэмплов с плавной поправкой аппаратного времени |
| `voice_playback_buffer.h` | Адаптивный запас готового PCM: увеличение после недостачи и уменьшение при стабильном выводе |
| `audiorecorder.h/cpp` | Захват голосовых сообщений, worker обработки PCM, компрессор, индикатор уровня и передача записи задаче |
| `voicemessageencoder.h/cpp` | Выбор Opus preset и создание медиа-каталога; кодирование выполняет общий voice_file |
| `voiceplayback.h/cpp` | Воспроизведение голосовых сообщений |
| `callwindow.h/cpp` | Окно звонка: состояния, управление, путь соединения и статистика аудио |
| `callwindow.h/cpp` | Окно аудио/видеозвонка: управление, выбор камеры, локальное/удалённое видео и статистика |
| `call_audio_engine.h/cpp` | Desktop-контур звонка: захват, VoiceAudioIo, общий выход SoundManager и завершение аудиосессии |
| `call_video_engine.h/cpp` | Desktop-видеозвонок: камера, TX/RX workers, обмен с ядром и показ кадров по аудиочасам |
| `call_video_encoder.h/cpp` | Кодер звонка: согласованный формат, смена битрейта с drain прежнего кодера и подтверждение настройки |
| `call_video_decoder.h/cpp` | FFmpeg-декодер H.264/H.265 с выбором GPU/CPU и сохранением PTS при задержанном выходе |
| `video_capture.h/cpp` | Асинхронный capture-процесс, каталог источников, watchdog и независимое от GUI закрытие |
| `video_capture_worker.cpp` | Камера/экран/окно, преобразование в CPU RGB32 и диагностика этапов аппаратного закрытия |
| `video_capture_source.h` | Контракт backend внутри worker и точка входа для тестовых источников |
| `video_capture_protocol.h` | Поколения, FRAME/ACK, этапы/heartbeat и ограничения IPC видеозахвата |
| `video_capture_buffer.h` | Однокадровый shared-memory буфер согласованной ёмкости до 4096×4096 RGB32 |
| `call_camera_rate.h` | Временное отключение снижения FPS из-за автоэкспозиции V4L2 с восстановлением настройки камеры |
| `call_video_cadence.h` | Отбор исходных кадров под заданный FPS без накопления ошибки дробного периода |
| `call_video_capture_clock.h` | Привязка времени камеры к монотонным часам с коррекцией задержки первого callback |
| `call_video_queue.h` | Ограниченная SPSC-очередь кадров между video workers без mutex и выделений памяти |
| `call_video_wake.h` | Пробуждение video worker по событию или абсолютному монотонному deadline на POSIX/Windows |
| `radio_audio_engine.h/cpp` | Desktop-контур рации: независимые захват/прослушивание, PTT/VAD и подключение к общему выходу |
| `radiopanel.h/cpp` | Панель активной рации: выбор аудиоустройств, VAD, PTT и состояние передачи из ядра |
| `radiosettingspage.h/cpp` | Настройки рации и запись глобальных сочетаний PTT |
| `ptt_hotkey_manager.h/cpp` | Глобальный PTT: физические клавиши Windows/X11, системный портал Wayland |
| `ptt_key_chord.h` | Хранение физических сочетаний с отдельными левыми/правыми модификаторами и запись одновременного нажатия |
| `ptt_portal.h/cpp` | D-Bus-сессия GlobalShortcuts для Wayland, настройка сочетаний и обработка нажатий/отпусканий |
| `media_blocks.h/cpp` | Чтение/сборка фрагментированных медиафайлов |
| `imageviewer_window.h/cpp` | Окно просмотра изображений |
| `videoplayer_engine.h/cpp` | Движок декодирования видео |
| `videoplayer_window.h/cpp` | Окно просмотра видео |
| `live_video_encoder.h/cpp` | Общий FFmpeg-кодер live-видео для звонка/трансляции, GPU/CPU, KEY-конфигурация и capture PTS |
| `video_frame_image.h` | Выделение выровненного RGB-буфера FFmpeg и передача владения QImage без копирования |
| `stream_publish_engine.h/cpp` | Публикация камеры/экрана и Opus: workers кодирования, локальный preview и завершение через общий publisher |
| `stream_publish_window.h/cpp` | Настройки и управление трансляцией; закрытие окна сохраняет работающий engine |
| `stream_portal_capture.h/cpp` | Захват экрана Wayland через ScreenCast portal/PipeWire, выбор монитора и режима курсора |
| `stream_screen_cursor.h/cpp`, `stream_screen_cursor_win.cpp` | Наложение системного курсора на кадр выбранного экрана средствами X11/Windows |
| `stream_video_modes.h` | Выбор размеров/FPS камеры и пропорционального масштабирования экрана для трансляции |
| `stream_qp_control.h` | Плавная корректировка потолка QP по фактическому выходному видеобитрейту |
| `stream_sources.h` | Разбор снимка активных источников канала из CHAT_EVT_STREAM_SOURCES |
| `streamplayer_window.h/cpp` | Просмотр live-потока: отдельные audio/video workers, смешивание PCM и синхронизация по часам устройства |
| `streamgrid_window.h/cpp` | Сетка трансляций канала и разворачивание плитки с сохранением плееров; своя плитка использует локальный preview |
| `connmonitorwindow.h/cpp` | Окно мониторинга ETCP-соединений (standalone) |
| `qrcode_utils.h/cpp` | Утилиты для QR-кодов |
| `debug_ui.h` | Отладочный UI |
@@ -745,9 +866,14 @@ cmake .. && make -j4
- `db/` — `db_manager.h/cpp`: доступ GUI к данным nodes, channels, msg_<channel>, peers_<channel> и состоянию интерфейса;
копия `db/sqlite3.c/h` не используется текущей CMake-целью, SQLite берётся из `lib/`
- `transport/` — интеграция GUI с ядром; файлы перечислены ниже
- `src/avatars/` — `avatarmanager.h/cpp`: загрузка/публикация аватаров участников через member_files, подписанные ссылки и очередь передач;
`avatarcache.h/cpp`: дисковый кеш, подготовка изображений и очистка; `avatarcrop.h/cpp`: выбор области;
`avatargallery.h/cpp`: просмотр аватаров пользователя; `groupavatarmanager.h/cpp`: подготовка и кеш подписанных аватарок каналов
- `src/member_files/` — `browser.h/cpp`: браузер серверных файлов группы; `batch.h/cpp`: последовательные операции над файлами/деревьями,
фоновый локальный обход, загрузка/скачивание и отмена
- `libutun/CMakeLists.txt` — состав и зависимости CMake-сборки общего ядра из `src/` и `lib/`
- `CMakeLists.txt` — приложение vibechat, Qt-зависимости, ресурсы и цели GUI-тестов
- `tests/` — проверки аудиоустройств и восстановления, голосового тракта, jitter-буферов, PTT, кодирования и GUI-компонентов
- `tests/` — проверки аудиотракта, PTT, видеозвонка, захвата камеры/экрана, трансляций, файлового браузера и GUI-компонентов
- `resources/` — `bg.jpg`, `chatgui.qrc` (встраивает 5 TGS в бинарник), `animations/*.tgs`
- `zxing-cpp/` — встроенная библиотека QR-кодов; `third_party/qhotkey/` — исходники QHotkey
@@ -761,6 +887,7 @@ cmake .. && make -j4
| `config_updater.h/cpp` | Изменение настроек в конфиге |
| `miniaudio_impl.c` | Реализация single-header miniaudio в отдельной единице трансляции |
| `audio_diagnostics.h/cpp` | Диагностика этапов аудио и событий backend; записывает метаданные без PCM |
| `stream_bridge.h/cpp` | Потокобезопасный мост к общим publisher/viewers: session IDs, каталог источников, запросы батчей и пробуждение workers |
### Система анимированных эмодзи
@@ -864,6 +991,13 @@ void lottie_animation_destroy(Lottie_Animation *anim);
- `src/routing_layer/topo_group.h` — протокол групповой сессии и критерий READY
- `tests/test_chat_join_e2e.c`, `tests/test_topo_recovery.c`, `tests/test_services.c` — проверки join, recovery и жизненного цикла
- `doc/dm_arch.md`, `doc/chat_call_arch.md` — личные сообщения и звонки
- `doc/call_video.txt` — видеотрек звонка: возможности кодеков, транспорт, битрейт, аудиочасы и показ кадров
- `doc/stream.txt` — трансляции: RS-пачки, выдачи/relay, выбор поставщиков, медиакурсоры и платформенные плееры
- `doc/stun_nat.md`, `doc/nat_detection.txt` — STUN-измерения и определение доступности рабочих UDP-сокетов
- `doc/member_files.txt` — файловое хранилище участников, права, wire-команды и передачи
- `doc/group_avatar.txt` — подписанная аватарка канала, хранение и репликация
- `doc/encrypted_attachments.md` — контейнер группового вложения, запросы ключа и ручная выдача доступа
- `doc/pm_invites.md`, `doc/message_links.md` — приглашения из личной беседы и ссылки внутри сообщений
- `doc/proxy_protocol.md` — TCP/UDP/ICMP-прокси, управление окнами, half-close и проверки
- `doc/lwip_nuances.md` — особенности адаптированного lwIP TCP-стека
- `doc/linux_audio_recovery.md` — диагностика аудиотракта Linux, контракты владения и восстановление устройств
@@ -906,7 +1040,11 @@ C-библиотека `utun_lite` собирает `lib/` и `src/` по `libut
| `libutun_lite/photo_sender.c/h` | Отправка фотографий в канал с MIME-типом и размерами изображения |
| `libutun_lite/video_sender.c/h` | Отправка видео через общий механизм подготовки вложений |
| `libutun_lite/voice_recorder.c/h` | Накопление PCM записи, компрессор и отправка голоса через общий attachment_send |
| `libutun_lite/stream_bridge.c/h` | Android-мост к publisher/viewers: session IDs, готовые access units/Opus и ограниченные батчи треков |
| `jni_bridge/android_jni_bridge.c/h` | JNI-команды и callbacks между Kotlin и C-ядром, события и аудио API |
| `jni_bridge/android_call_output_jni.c` | Вывод PCM звонка через AAudio с аппаратным тактированием и снимками позиции устройства |
| `jni_bridge/android_call_video_jni.c` | JNI видеозвонка: capabilities/формат, обмен кадрами с call_video_port, playout и поворот YUV |
| `jni_bridge/android_stream_jni.c` | JNI трансляций: publisher/viewer API, Opus/SoundTouch, готовый PCM и часы воспроизведения |
| `jni_bridge/android_udp_log.c/h` | Потокобезопасный буфер UDP-логов с flush-таймером в потоке ядра |
| `headless/headless_main.c` | Отдельный каркас control-loop; сам не запускает ядро/чат |
| `headless/headless_control.c/h` | Каркас control-сокета; часть команд — заглушки, рабочий API — src/chat/chat_headless_control.c/h |
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="ua.cn.stu.navigation">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
tools:ignore="CoarseFineLocation" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Navigation">
<activity
android:name=".MainActivity"
android:exported="true"
android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".ble.BluetoothLeService"
android:enabled="true" />
</application>
</manifest>
Binary file not shown.
+99
View File
@@ -0,0 +1,99 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.18.1)
# Declares and names the project.
project("bt_drv")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
bt_drv
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
bt_drv.c
ble_tcp.c
ble_eth.c
eth_mem.c
eth_router.c
eth_nat.c
eth_queue.c
xlib.c
settings.c
images.c
# LWIP
# lwip/api/api_lib.c
#// lwip/api/api_msg.c
#// lwip/api/err.c
#// lwip/api/if_api.c
#// lwip/api/tcpip.c
lwip/dnsproxy.c
lwip/dhcp_server.c
lwip/net_raw.c
lwip/net_topology.c
lwip/lwip.c
lwip/eth_router_if_lwip.c
lwip/core/def.c
lwip/core/inet_chksum.c
lwip/core/init.c
lwip/core/ip.c
lwip/core/mem.c
lwip/core/memp.c
lwip/core/netif.c
lwip/core/pbuf.c
lwip/core/raw.c
lwip/core/stats.c
lwip/core/sys.c
lwip/core/tcp.c
lwip/core/tcp_in.c
lwip/core/tcp_out.c
lwip/core/timeouts.c
lwip/core/udp.c
lwip/core/ipv4/icmp.c
lwip/core/ipv4/ip4.c
lwip/core/ipv4/ip4_addr.c
lwip/core/ipv4/ip4_frag.c
lwip/core/ipv4/etharp.c
lwip/netif/ethernet.c
)
include_directories(
.
lwip
lwip/include
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
bt_drv
# Links the target library to the log library
# included in the NDK.
${log-lib} )
+190
View File
@@ -0,0 +1,190 @@
#include <stdint.h>
#include <string.h>
#include <pthread.h>
#include "xlib.h"
#include "ble_eth.h"
#include "eth_mem.h"
#include "eth_router.h"
#include "ble_tcp.h"
//#define BLE_FLOOD_TEST
// модуль разобрки-сборки кодограмм на фрагменты. Работает вместе с ble_tcp и с ble_link
/* Формат посылки:
Кодограмма разбиватеся на куски. К каждому куску в начале добавляется один байт.
Формат байта: байт0 биты 6,7 - тип посылки. Биты 0-5 будут перезаписаны при передаче.
bit7:6 - тип кодограммы:
00 (0x00) - промежуточный блок кодограммы
01 (0x40) - первый блок кодограммы
10 (0x80) - последний блок кодограммы
11 (0xC0) - вся кодограмма в одном фрагменте
*/
struct BLE_ETH_STATS ble_eth_stats;
static struct ETH_PBUF* current_tx_block=NULL;
static uint8_t eth_rst_req_rx;
static uint8_t tx_rst=0;
void gatt_eth_reset() {
eth_rst_req_rx=1;
tx_rst=1;
}
static struct ETH_PBUF* rx_pbuf=NULL;
static uint16_t rx_ptr;
static uint8_t rx_prev_seq;
static uint8_t rx_seq_err;
int process_dgram_asm(uint8_t* data, uint16_t len) {// BLE to ETH_router
ble_eth_stats.rx_chunks++;
if (len<2) { ble_eth_stats.rx_too_short_chunk++; return 0; }
// if (eth_netif_array[BLE_NETIF_ID].input_queue_len>IN_BLE_NETIF_QLEN_THR) { ble_eth_stats.rx_qpause++; return -1; }// очередь заполнена, временно не принимаем новое (loopback test mode)
// если очередь полная, то приостановим поток
if (eth_rst_req_rx) {
eth_rst_req_rx=0;
if (rx_pbuf) {
eth_pbuf_free_request(rx_pbuf);
rx_pbuf=NULL;
}
rx_ptr=0;
}
uint8_t dg_type=data[0]&0x0C0;
uint8_t dg_seq=data[0]&0x03F;
if (dg_type & 0x40) {// first block
rx_ptr=0;
rx_seq_err=0;
rx_prev_seq=(dg_seq-1)&0x03F;
if (rx_pbuf==NULL) rx_pbuf=eth_pbuf_alloc(&xeth_pbuf_ctrl, NULL);
if (rx_pbuf==NULL) { ble_eth_stats.rx_pbuf_alloc_err++; return -1; }
}
if (rx_pbuf!=NULL) {
rx_prev_seq=(rx_prev_seq+1)&0x3F;
if (rx_prev_seq!=dg_seq || rx_seq_err) {
ble_eth_stats.rx_seqerr++;
eth_pbuf_free_request(rx_pbuf);
rx_pbuf=NULL;
return 0;
}
len--;
if (rx_ptr+len<=ETH_MEM_BUF_SIZE) {
memcpy((uint8_t*)rx_pbuf->pbuf.payload+rx_ptr, data+1, len);
rx_ptr+=len;
if (dg_type & 0x080) {// last block
rx_pbuf->pbuf.len=rx_ptr;
rx_pbuf->pbuf.tot_len=rx_ptr;
rx_pbuf->pbuf.if_idx=BLE_NETIF_ID;
if (rx_ptr>=14) { ble_eth_stats.rx_dgrams++; eth_add_packet_to_router_queue(rx_pbuf); }
else { ble_eth_stats.rx_too_short_dgram++; eth_pbuf_free_request(rx_pbuf); }
rx_pbuf=NULL;
}
}
else {// invalid block
ble_eth_stats.rx_oversize++;
eth_pbuf_free_request(rx_pbuf);
rx_pbuf=NULL;
}
}
return 0;
}
#define MAX_CHUNK_LEN 167//239
static uint16_t chunk_len;// for BLE - current chunk length
static uint16_t tx_ptr;// pointer for chunks
static int cbk_pending=0;
int get_next_chunk(uint8_t* chunk_for_tx) {// взять новый блок. Или NULL если блока нет (если блока нет - будет вызван коллбэк)
if (tx_rst) {
tx_rst=0;
tx_ptr=0;
}
#ifdef BLE_FLOOD_TEST
ble_eth_stats.tx_chunks++;
chunk_for_tx[0]=0xC0;
return 240;// for test
#endif
if (cbk_pending) return 0;
if (current_tx_block==NULL) {
cbk_pending=1;
struct ETH_PBUF* tb=eth_get_packet(&eth_netif_array[BLE_NETIF_ID]);
if (tb==NULL) {
return 0;// waiting for callback
} else { current_tx_block=tb; cbk_pending=0; }
}
uint8_t pkt_sent;// 0 - no data; 1 - send in progress, 2 - send finished
int32_t len=current_tx_block->pbuf.len-tx_ptr;
if (tx_ptr==0) chunk_for_tx[1]=0x40; else chunk_for_tx[1]=0;
if (len>MAX_CHUNK_LEN) { len=MAX_CHUNK_LEN; pkt_sent=0; } else { chunk_for_tx[1]|=0x80; pkt_sent=1; }
chunk_len=len+2;
memcpy(&chunk_for_tx[2], (uint8_t*)(current_tx_block->pbuf.payload)+tx_ptr, len);
tx_ptr+=len;
if (pkt_sent) {// последний блок скопирован в chunk_for_tx. пакат можно освобождать
ble_eth_stats.tx_dgrams++;
eth_pbuf_free_request(current_tx_block);
current_tx_block=NULL;
tx_ptr=0;
}
ble_eth_stats.tx_chunks++;
return chunk_len;
}
void next_chunk_avail();
static void callback_from_bridge(struct ETH_PBUF* block, struct ETH_NETIF* enetif) {// появился пакет на передачу
current_tx_block=block;
cbk_pending=0;
next_chunk_avail();
}
void ble_callback_qlen(struct ETH_NETIF* netif) {
if (netif->input_queue_len<IN_BLE_NETIF_QLEN_THR) {// обновилась очередь в роутере - позволяет забрать пакет
notify_ble_out_queue();
}
}
_Noreturn void tcp_test_Task(void * arg) {
while(1) {
struct ETH_PBUF* block=eth_pbuf_alloc(&xeth_pbuf_ctrl, NULL);
if (block) {
memset(block->pbuf.payload, 0,1000);
char* d=(char*)block->pbuf.payload;
d[0]=1;
d[1]=2;
d[2]=3;
d[3]=4;
d[4]=5;
d[5]=6;
block->pbuf.len=230;
block->pbuf.tot_len=230;
block->pbuf.if_idx=LWIP_NETIF_ID;
eth_add_packet_to_router_queue(block);
}
usleep(1000*500);
}
}
pthread_t ttHandle;
void eth_ble_if_init() {
eth_netif_array[BLE_NETIF_ID].callback_fn=callback_from_bridge;// инициализируем callback (пакет готов)
eth_netif_array[BLE_NETIF_ID].q_output_len_max=BLE_NETIF_QLEN;
eth_netif_array[BLE_NETIF_ID].q_update_cbk=ble_callback_qlen;
eth_netif_array[BLE_NETIF_ID].if_up=1;
// TaskCreate (tcp_test_Task, &ttHandle);
eth_netif_array[TEST_NETIF_ID].q_output_len_max=BLE_NETIF_QLEN;
eth_netif_array[TEST_NETIF_ID].if_up=1;
}
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include <stdint.h>
#define MAX_CHUNK_LEN 167
struct BLE_ETH_STATS {
uint32_t tx_chunks;
uint32_t rx_chunks;
uint32_t tx_dgrams;
uint32_t rx_dgrams;
uint32_t rx_too_short_chunk;
uint32_t rx_too_short_dgram;
uint32_t rx_oversize;
uint32_t rx_pbuf_alloc_err;
uint32_t rx_qpause;
uint32_t rx_seqerr;
uint32_t d1;
uint32_t d2;
uint32_t d3;
uint32_t d4;
};
extern struct BLE_ETH_STATS ble_eth_stats;
int get_next_chunk(uint8_t* chunk_for_tx);
int process_dgram_asm(uint8_t* data, uint16_t len);
void eth_ble_if_init();
void gatt_eth_reset();
+196
View File
@@ -0,0 +1,196 @@
#include <jni.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include "ble_tcp.h"
#include "xlib.h"
#include "bt_drv.h"
#include "eth_mem.h"
#include "eth_router.h"
#include "ble_eth.h"
// модуль обеспечивающий ретрансмиссии, буферизацию, контроль потока для GATT посылок.
#define ACK_MIN_INTERVAL 25// mS. на эту величину может задерживаться отправка ACK
//#define print_pkt_body
static uint32_t last_ack_time;
static uint8_t ack_sent_value;
static uint8_t snd_blk_len;
static uint8_t snd_blk[MAX_CHUNK_LEN+2];
static struct itimerspec trigger;
static timer_t timerid;
static uint8_t ack_notify_request;
#define TMR_CHECK_TXBUF_PERIOD 100
//static TimerHandle_t xTcpTimer;
static struct NHandle_t tNotifyHandle;
pthread_t tHandle;
pthread_t tHandle1;
sem_t tcp_tx_sem;
sem_t tcp_rx_sem;
#define TX_LOCK sem_wait(&tcp_tx_sem)
#define TX_UNLOCK sem_post(&tcp_tx_sem)
#define RX_LOCK sem_wait(&tcp_rx_sem)
#define RX_UNLOCK sem_post(&tcp_rx_sem)
#define taskNOTIFY_ACK_UPDATE 1// очередь передачи
#define taskNOTIFY_NEXT_CHUNK_AVAIL 2
#define taskNOTIFY_NEXT_CHUNK_FOR_TX_AVAIL 4
#define taskNOTIFY_BLE_TX_COMPLETE 8
#define taskNOTIFY_nACK_UPDATE 16// приемная очередь
#define taskNOTIFY_TMR_IDLE 64
#define taskNOTIFY_PUSH_RECVD 256
struct BLE_TCP_STATS ble_tcp_stats;
struct BLE_TCP ble_tcp;
uint8_t tx_index_blk;// ячейка ожидающая передачу
uint8_t tx_push_ptr_blk;// ячейка ожидающая добавление элемента
static uint32_t tx_last_time;// ячейка ожидающая добавление элемента
uint8_t rx_nack_blk;// циклический номер блока, ожидающего приём
void gatt_conn_reset() {
TX_LOCK;
RX_LOCK;
ble_tcp.ble_tx_busy=0;
ble_tcp_stats.rst_cnt++;
rx_nack_blk=1;
tx_index_blk=0;
tx_push_ptr_blk=0;
snd_blk_len=0;
gatt_eth_reset();
TNotifyAdd( &tNotifyHandle, taskNOTIFY_BLE_TX_COMPLETE);
RX_UNLOCK;
TX_UNLOCK;
}
void notify_ble_out_queue() {// callback: обновилась очередь ETH / ble_if
TNotifyAdd(&tNotifyHandle, taskNOTIFY_PUSH_RECVD);
}
void process_gatt_data(uint8_t* data, uint16_t len) {
ble_tcp_stats.rx_raw++;
if (len<1) { ble_tcp_stats.rx_empty_dg++; return; }
ble_tcp_stats.rx_bytes+=len;
#ifdef print_pkt_body
if (len==1) print_log("Recv %d bytes [%02x]", len, data[0]);
else print_log("Recv %d bytes [%02x %02x]", len, data[0], data[1]);
#endif
TX_LOCK;
rx_nack_blk=data[0]&0x3F;
TNotifyAdd( &tNotifyHandle, taskNOTIFY_nACK_UPDATE );
TX_UNLOCK;
if (len>1) {
RX_LOCK;
process_dgram_asm(data+1, len-1);
RX_UNLOCK;
}
}
void next_chunk_avail() {
TNotifyAdd( &tNotifyHandle, taskNOTIFY_NEXT_CHUNK_AVAIL );
}
void ble_tx_complete(int status) {
ble_tcp.ble_tx_busy=0;
TNotifyAdd( &tNotifyHandle, taskNOTIFY_BLE_TX_COMPLETE );// ззавершена передача. можно затолкать в буфер передачи еще
}
static int ble_gatt_trysend(uint8_t * data, uint16_t len) {
if (ble_connection_status!=2) return -3;// not ready for send
if (ble_tcp.ble_tx_busy) return -1;
ble_tcp.ble_tx_busy=1;
int ret=bt_send(data, len);// status: 1 - all ok, 0 - error
if (ret!=1) { ble_tcp.ble_tx_busy=0; return -2; }
ble_tcp_stats.tx_raw++;
#ifdef print_pkt_body
if (len==1) print_log("Send %d bytes [%02x]", len, data[0]);
else print_log("Send %d bytes [%02x %02x]", len, data[0], data[1]);
#endif
return 0;
}
// байт 1 (или 1+2) - rx ack / sack
_Noreturn void BLE_TCP_Task(void * arg) {
send_thread_register();// зарегистрировать в java VM этот поток для возможности совершать вызовы
while (1) {
uint32_t res=TNotifyWait( &tNotifyHandle );
// попробуем передать что накопилось
if ((res & (taskNOTIFY_BLE_TX_COMPLETE | taskNOTIFY_NEXT_CHUNK_AVAIL | taskNOTIFY_nACK_UPDATE | taskNOTIFY_TMR_IDLE)) && ble_tcp.ble_tx_busy==0) {
dbg[0]++;
TX_LOCK;
int idx=tx_index_blk;
int len=snd_blk_len;
if (len==0) {
len=get_next_chunk(&snd_blk[0]);
snd_blk_len=len;
}
if (len || (ack_notify_request && ack_sent_value!=rx_nack_blk )) {// шлем если есть что слать, либо пора отправить обновление по ACK
uint32_t ack=rx_nack_blk;
snd_blk[0]=ack;
if (len==0) len=1;
else snd_blk[1]=(idx&0x3F)|(snd_blk[1] & 0xC0);// сохраняем биты признака начала-конца кодограммы для разобрщика кодограмм
// 167 = 5 (800) *9=1503 (169 bytes max incl. headers)
int ret=ble_gatt_trysend(&snd_blk[0], len);// ack + dgram
if (ret==0) {
snd_blk_len=0;
ble_tcp_stats.tx_bytes+=len;
ble_tcp_stats.tx_blocks++;
ack_sent_value=ack;
ack_notify_request=0;
timer_settime(timerid, 0, &trigger, NULL);
tx_index_blk=(idx+1)&0x3F;
}
}
TX_UNLOCK;
}
}
}
static void tcp_tmr( void* arg ) {
TX_LOCK;
ack_notify_request=1;
TX_UNLOCK;
TNotifyAdd( &tNotifyHandle, taskNOTIFY_TMR_IDLE);// no activity. for timed-out retransmit
}
void ble_tcp_init() {
sem_init(&tcp_tx_sem, 0, 1);
sem_init(&tcp_rx_sem, 0, 1);
tx_last_time=xTaskGetTickCount();
TaskCreate (BLE_TCP_Task, &tHandle);
TNotifyCreate(&tNotifyHandle);
TNotifyAdd( &tNotifyHandle, taskNOTIFY_ACK_UPDATE);
struct sigevent sev;
memset(&sev, 0, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = &tcp_tmr;
memset(&trigger, 0, sizeof(struct itimerspec));
timer_create(CLOCK_REALTIME, &sev, &timerid);
trigger.it_value.tv_sec = ACK_MIN_INTERVAL/1000000;
trigger.it_value.tv_nsec = ACK_MIN_INTERVAL*1000000;
timer_settime(timerid, 0, &trigger, NULL);
}
+57
View File
@@ -0,0 +1,57 @@
struct BLE_TCP_STATS {
uint32_t tx_raw;
uint32_t rx_raw;
uint32_t tx_blocks;
uint32_t rx_blocks;
uint32_t tx_err;
uint32_t tx_ack_err;
uint32_t tx_sack_err;
uint32_t tx_ack_negdist_err;
uint32_t tx_ack_toomuch_err;
uint32_t ack_upd;
uint32_t rx_empty_dg;
uint32_t rx_only_ack;
uint32_t rx_seq_err;
uint32_t rx_dup_ack;
uint32_t rx_neg_ack;
uint32_t rx_duplicates;
uint32_t rx_detected_retransmit_jumps;
uint32_t rx_detected_packet_loss_single;
uint32_t rx_detected_packet_loss_multiple;
uint32_t rx_detected_incorrect_jumps;
uint32_t rst_cnt;
uint32_t rstreq_cnt;
uint32_t rxasm_throttle;
uint32_t rxasm_try;
uint32_t tx_bytes;
uint32_t rx_bytes;
uint32_t d1;
uint32_t d2;
uint32_t d3;
uint32_t d4;
};
extern struct BLE_TCP_STATS ble_tcp_stats;
struct BLE_TCP {
uint32_t ble_tx_busy;
};
extern struct BLE_TCP ble_tcp;
extern uint8_t tx_busy_mask[8];
extern uint8_t rx_ready_mask[8];
extern uint8_t rx_nack_blk;
extern uint8_t rx_last_recvd_blk;
extern uint8_t tx_ack_blk;// следующая после подтвержденной ячейка (т.е. начиная с которой надо передавать)
extern uint8_t tx_index_blk;// ячейка ожидающая передачу
extern uint8_t tx_push_ptr_blk;// ячейка ожидающая добавление элемента
void ble_tcp_init();
void notify_ble_out_queue();//
void ble_tx_complete(int status);
void process_gatt_data(uint8_t* data, uint16_t len);
void gatt_conn_reset();
+355
View File
@@ -0,0 +1,355 @@
#include <jni.h>
#include "bt_drv.h"
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sched.h>
#include <semaphore.h>
#include <stdatomic.h>
#include "xlib.h"
#include "ble_tcp.h"
#include "eth_mem.h"
#include "eth_router.h"
#include "ble_eth.h"
#include "lwip/lwip.h"
#include "eth_nat.h"
#include "lwip/net_topology.h"
//#include "lwip/opt.h"
//#include "lwip/mem.h"
//#include "lwip/memp.h"
//#include "lwip/netif.h"
//#include "lwip/init.h"
int dbg_scr_num=0;
// ====================================== startup =========================
JavaVM* gJvm = NULL;
jobject bleservice;
jclass bleserv;
jclass bleserv1;
JNIEnv* send_env;
JNIEnv* status_upd_env;
jmethodID send_method;
jmethodID frame_method;
jmethodID status_upd_method;
volatile int ble_connection_status=0;// 2 - connection up.
int bt_send(uint8_t* dgr, uint16_t dglen) {
dbg[3]++;
JNIEnv *env=send_env;
jbyteArray dgram=(*env)->NewByteArray(env, dglen);
if (dgram == NULL) return -1;
(*env)->SetByteArrayRegion (env, dgram, 0, dglen, dgr);
// jbyteArray bytes = (*env)->GetObjectField(env, obj, sendId)
// jbyte *stateJava = (*env)->GetByteArrayElements(env, dgram, NULL);
// if (stateJava == NULL) return -1;
// memcpy(stateJava, dgr, dglen);
int ret=-1;
if (send_method) ret=(*env)->CallStaticIntMethod(env, bleserv, send_method, dgram);
(*env)->DeleteLocalRef(env, dgram);
// print_log("[BLE] send dgram %d", ret);
return ret;
}
jbyteArray jname;
jbyteArray jval;
static void status_upd(int p, char* name, char* val) {
JNIEnv *env=status_upd_env;
jbyteArray jname=(*env)->NewByteArray(env, strlen(name));
if (jname == NULL) return;
(*env)->SetByteArrayRegion (env, jname, 0, strlen(name), name);
jbyteArray jval=(*env)->NewByteArray(env, strlen(val));
if (jval == NULL) return;
(*env)->SetByteArrayRegion (env, jval, 0, strlen(val), val);
if (status_upd_method) (*env)->CallStaticVoidMethod(env, bleserv1, status_upd_method, p, jname, jval);
(*env)->DeleteLocalRef(env, jname);
(*env)->DeleteLocalRef(env, jval);
}
void status_upd_thread_register() {
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6; // choose your JNI version
args.name = NULL;
args.group = NULL;
jint ret=(*gJvm)->AttachCurrentThread(gJvm, &status_upd_env, &args);
if (ret) return;
}
void send_thread_register() {
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6; // choose your JNI version
args.name = NULL;
args.group = NULL;
jint ret=(*gJvm)->AttachCurrentThread(gJvm, &send_env, &args);
if (ret) return;
}
void status_upd1(int i, char* b, uint32_t c) {
char str[100];
sprintf(str, "%d",c);
status_upd(i, b, str);
}
uint32_t tx_hist[16];
uint32_t rx_hist[16];
uint32_t htime[16];
uint8_t histptr;
pthread_t thr;
_Noreturn void status_thread(void* arg) {
status_upd_thread_register();
while(1) {
int p=histptr&15;
tx_hist[p]=ble_tcp_stats.tx_bytes;
rx_hist[p]=ble_tcp_stats.rx_bytes;
htime[p]=xTaskGetTickCount();
int tx_spd=(tx_hist[p]-tx_hist[(p-10)&15])*1000/(htime[p]-htime[(p-10)&15]);
int rx_spd=(rx_hist[p]-rx_hist[(p-10)&15])*1000/(htime[p]-htime[(p-10)&15]);
p++;
histptr=p&15;
dbg[1]=(dbg[1]+1)%170;
int i = 1;
if (dbg_scr_num==0) {
status_upd1(i++, "dbg[0]", dbg[0]);
status_upd1(i++, "dbg[1]", dbg[1]);
status_upd1(i++, "dbg[2]", dbg[2]);
status_upd1(i++, "dbg[3]", dbg[3]);
status_upd1(i++, "dbg[4]", dbg[4]);
status_upd1(i++, "dbg[5]", dbg[5]);
status_upd1(i++, "dbg[6]", dbg[6]);
status_upd1(i++, "dbg[7]", dbg[7]);
status_upd1(i++, "dbg[8]", dbg[8]);
status_upd1(i++, "dbg[9]", dbg[9]);
status_upd1(i++, "dbg[10]", dbg[10]);
status_upd1(i++, "tx_chunks", ble_eth_stats.tx_chunks);
status_upd1(i++, "rx_chunks", ble_eth_stats.rx_chunks);
status_upd1(i++, "tx_dgrams", ble_eth_stats.tx_dgrams);
status_upd1(i++, "rx_dgrams", ble_eth_stats.rx_dgrams);
status_upd1(i++, "rx_qpause", ble_eth_stats.rx_qpause);
status_upd1(i++, "rx_seqerr", ble_eth_stats.rx_seqerr);
status_upd1(i++, "tx_spd", tx_spd);
status_upd1(i++, "rx_spd", rx_spd);
}
if (dbg_scr_num==1) {
status_upd1(i++, "ble_conn_status", ble_connection_status);
status_upd1(i++, "BLEif_dg_in", eth_netif_array[BLE_NETIF_ID].dgrams_in);
status_upd1(i++, "BLEif_dg_lost", eth_netif_array[BLE_NETIF_ID].dgrams_lost);
status_upd1(i++, "BLEif_dg_out", eth_netif_array[BLE_NETIF_ID].dgrams_out);
status_upd1(i++, "BLEif_dg_outqlen", eth_netif_array[BLE_NETIF_ID].q_output_len);
status_upd1(i++, "BLEif_dg_in_qlen", eth_netif_array[BLE_NETIF_ID].input_queue_len);
status_upd1(i++, "BLEif_cbk_p", eth_netif_array[BLE_NETIF_ID].callback_pending);
status_upd(i++, "", "");
status_upd1(i++, "LWif_dg_in", eth_netif_array[LWIP_NETIF_ID].dgrams_in);
status_upd1(i++, "LWif_dg_lost", eth_netif_array[LWIP_NETIF_ID].dgrams_lost);
status_upd1(i++, "LWif_dg_out", eth_netif_array[LWIP_NETIF_ID].dgrams_out);
status_upd1(i++, "LWif_dg_outqlen", eth_netif_array[LWIP_NETIF_ID].q_output_len);
status_upd1(i++, "LWif_dg_in_qlen", eth_netif_array[LWIP_NETIF_ID].input_queue_len);
status_upd1(i++, "LWif_cbk_p", eth_netif_array[LWIP_NETIF_ID].callback_pending);
status_upd(i++, "", "");
status_upd1(i++, "NAT_pbuf_brk", nat_stat.pbuf_broken);
status_upd1(i++, "NAT_tcp_new", nat_stat.tcp_new);
status_upd1(i++, "NAT_tcp_close", nat_stat.tcp_close);
status_upd(i++, "", "");
status_upd1(i++, "eth_pbuf used", xeth_pbuf_ctrl.used);
status_upd1(i++, "eth_queue used", xeth_queuepool_ctrl.used);
status_upd1(i++, "nat pbuf used", nat_stat.pbuf_used);
status_upd1(i++, "nat lw conn used", nat_stat.lw_conn_used);
}
if (dbg_scr_num==2) {
status_upd1(i++, "tx_raw", ble_tcp_stats.tx_raw);
status_upd1(i++, "rx_raw", ble_tcp_stats.rx_raw);
status_upd1(i++, "tx_blocks", ble_tcp_stats.tx_blocks);
status_upd1(i++, "rx_blocks", ble_tcp_stats.rx_blocks);
status_upd1(i++, "tx_err", ble_tcp_stats.tx_err);
status_upd1(i++, "tx_ack_err", ble_tcp_stats.tx_ack_err);
status_upd1(i++, "tx_sack_err", ble_tcp_stats.tx_sack_err);
// status_upd1(i++, "tx_ack_negd_err", ble_tcp_stats.tx_ack_negdist_err);
// status_upd1(i++, "tx_ack_toom_err", ble_tcp_stats.tx_ack_toomuch_err);
// status_upd1(i++, "ack_upd", ble_tcp_stats.ack_upd);
// status_upd1(i++, "rx_empty_dg", ble_tcp_stats.rx_empty_dg);
// status_upd1(i++, "rx_only_ack", ble_tcp_stats.rx_only_ack);
status_upd1(i++, "rx_seq_err", ble_tcp_stats.rx_seq_err);
// status_upd1(i++, "rx_dup_ack", ble_tcp_stats.rx_dup_ack);
// status_upd1(i++, "rx_neg_ack", ble_tcp_stats.rx_neg_ack);
status_upd1(i++, "rx_duplicates", ble_tcp_stats.rx_duplicates);
status_upd1(i++, "rx_rtr_jmps", ble_tcp_stats.rx_detected_retransmit_jumps);
// status_upd1(i++, "rx_pl1", ble_tcp_stats.rx_detected_packet_loss_single);
// status_upd1(i++, "rx_pl2+", ble_tcp_stats.rx_detected_packet_loss_multiple);
status_upd1(i++, "rx_incor_jmps", ble_tcp_stats.rx_detected_incorrect_jumps);
char b[100]; int ptr=0;
// for (int i=0; i<8; i++) ptr+=sprintf(b+ptr, "%d ",tx_busy_mask[i]);
status_upd(i++, "tx_busy_mask", b);
// status_upd1(i++, "tx_ack_blk", tx_ack_blk);
status_upd1(i++, "tx_index_blk", tx_index_blk);
status_upd1(i++, "tx_push_ptr_blk", tx_push_ptr_blk);
ptr=0;
// for (int i=0; i<8; i++) ptr+=sprintf(b+ptr, "%d ",rx_ready_mask[i]);
status_upd(i++, "rx_ready_mask", b);
status_upd1(i++, "rx_nack_blk", rx_nack_blk);
// status_upd1(i++, "rx_last_rcvd_blk", rx_last_recvd_blk);
status_upd1(i++, "conn_rst", ble_tcp_stats.rst_cnt);
status_upd1(i++, "conn_rst_req", ble_tcp_stats.rstreq_cnt);
status_upd1(i++, "ble_tx_busy", ble_tcp.ble_tx_busy);
status_upd1(i++, "rxasm_try", ble_tcp_stats.rxasm_try);
status_upd1(i++, "rxasm_throttle", ble_tcp_stats.rxasm_throttle);
}
while (i<=30) status_upd(i++, "", "");
usleep(100000);
}
}
JNIEXPORT void JNICALL
Java_ua_cn_stu_navigation_MainActivity_change_1dbg_1scr(JNIEnv *env, jobject thiz, jint scr) {
dbg_scr_num=scr;
}
pthread_t frameThreadHandle;
extern uint8_t imageCubes[];
extern uint8_t imageWolf[];
JNIEnv* frame_env;
void frameThread(void *argsw)
{
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6; // choose your JNI version
args.name = NULL;
args.group = NULL;
jint ret=(*gJvm)->AttachCurrentThread(gJvm, &frame_env, &args);
if (ret) return;
static unsigned char parity;
while(1)
{
usleep(50000);
if (frame_method)
{
JNIEnv *env = frame_env;
jbyteArray dgramm = (*env)->NewByteArray(env, 132 * 8);
if (dgramm == NULL) continue;
(*env)->SetByteArrayRegion (env, dgramm, 0, 132 * 8, ! parity ? imageWolf : imageCubes);
(*env)->CallStaticVoidMethod(env, bleserv, frame_method, dgramm);
(*env)->DeleteLocalRef(env, dgramm);
parity = !parity;
}
}
}
void frameThreadInit()
{
TaskCreate (frameThread, &frameThreadHandle);
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* pjvm, void* reserved) {
gJvm = pjvm;
JNIEnv* env;
if ((*pjvm)->GetEnv(pjvm, &env, JNI_VERSION_1_6) != JNI_OK) {return JNI_ERR;}
bleserv = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "ua/cn/stu/navigation/MainActivity"));
if (bleserv == NULL) return JNI_ERR;
bleserv1 = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "ua/cn/stu/navigation/MainActivity"));
if (bleserv1 == NULL) return JNI_ERR;
send_method = (*env)->GetStaticMethodID(env, bleserv, "send_to_ble","([B)I");
if (send_method == NULL) return JNI_ERR;
frame_method = (*env)->GetStaticMethodID(env, bleserv, "frame", "([B)V");
if (frame_method == NULL) return JNI_ERR;
status_upd_method = (*env)->GetStaticMethodID(env, bleserv, "upd_status_param","(I[B[B)V");
if (status_upd_method == NULL) return JNI_ERR;
TaskCreate(status_thread, &thr);
eth_router_init();
eth_ble_if_init();
ble_tcp_init();
MX_LWIP_Init();
topology_init();
frameThreadInit();
return JNI_VERSION_1_6;
}
//JNIEXPORT void JNICALL Java_ua_cn_stu_navigation_MainActivity_char_1wr_1cbk(JNIEnv *env, jobject thiz, jint status) {
// ble_tx_complete(status);
//}
JNIEXPORT void JNICALL
Java_ua_cn_stu_navigation_ble_BluetoothLeService_char_1wr_1cbk(JNIEnv *env, jclass clazz,
jint status) {
ble_tx_complete(status);
}
JNIEXPORT void JNICALL
Java_ua_cn_stu_navigation_MainActivity_new_1dg_1from_1bt(JNIEnv *env, jobject thiz, jbyteArray jdgram) {
dbg[4]++;
jbyte *stateJava = (*env)->GetByteArrayElements(env, jdgram, NULL);
if (stateJava == NULL) return ;
jint len = (*env)->GetArrayLength(env, jdgram);
if (len>0) process_gatt_data(stateJava, len);
// int pid=getpid();
// int ppid=getppid();
// int tid = gettid();
// print_log("tid %d pid %d ppid %d recvd %d bytes",tid, pid, ppid, len);
(*env)->ReleaseByteArrayElements(env, jdgram, stateJava, 0);
}
JNIEXPORT void JNICALL
Java_ua_cn_stu_navigation_MainActivity_eth_1ble_1stack_1control(JNIEnv *env, jobject thiz,
jint status) {
// status:
// 0 - service started
// 1 - service shutdown request
// 2 - ble connection up
// 3 - ble connection down
ble_connection_status=status;
if (status==2) gatt_conn_reset();
}
JNIEXPORT void JNICALL
Java_ua_cn_stu_navigation_MainActivity_tap_1detected(JNIEnv *env, jobject thiz, jint area) {
// tap_detected(area);
dbg[2]++;
}
JNIEXPORT void JNICALL
Java_ua_cn_stu_navigation_MainActivity_coord_1from_1terminal(JNIEnv *env, jobject thiz, jint x_pix,
jint y_pix) {
static volatile char x;
x++;
// TODO: implement coord_from_terminal()
}
JNIEXPORT void JNICALL
Java_ua_cn_stu_navigation_MainActivity_button_1from_1terminal(JNIEnv *env, jobject thiz,
jint button_id) {
volatile int lol = button_id;
// TODO: implement button_from_terminal()
}
//JNIEXPORT void JNICALL Java_ua_cn_stu_navigation_MainActivity_eth_1ble_1stack_1control(JNIEnv *env, jobject thiz, jint status) {
//// status:
//// 0 - service started
//// 1 - service shutdown request
//// 2 - ble connection up
//// 3 - ble connection down
// ble_connection_status=status;
// if (status==2) gatt_conn_reset();
//}
+9
View File
@@ -0,0 +1,9 @@
#ifndef TESTBLE_BT_DRV_H
#define TESTBLE_BT_DRV_H
#include <jni.h>
int bt_send(uint8_t* dgr, uint16_t dglen);
void send_thread_register();
extern volatile int ble_connection_status;
#endif //TESTBLE_BT_DRV_H
+377
View File
@@ -0,0 +1,377 @@
// ETH_MEM ver 1.0
#include "xlib.h"
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include "eth_mem.h"
#include "eth_router.h"
sem_t eth_mem_sem;
// ============ task for queue management
struct ETH_MEM_STATS eth_mem_stats;
// private function prototypes
static void EthQueueTask(void *argument);
static void eth_custom_pbuf_free_request(struct pbuf* p);
#define taskNOTIFY_NEW_FREE_P_REQUEST 1// освобождение элемента очереди
#define taskNOTIFY_NEW_P_REQUEST 4// дефицит pbuf
#define taskNOTIFY_ROUTER_Q_UPDATE 16// толкнуть обработчик очередей (роутер)
// ref увеличивается только в главном пакете из цепочки.
inline static struct ETH_PBUF* do_eth_pbuf_alloc(struct ETH_PBUF_CTRL* eth_pbuf_ctrl, struct NOMEM_CALLBACK* cb) {
struct ETH_PBUF* p=(struct ETH_PBUF*)eth_pbuf_ctrl->free_chain;
if (p==NULL) {// no memory
if (cb) {
if (cb->wait_active) return NULL;
eth_mem_stats.eth_pbuf_alloc_delayed++;
if (eth_mem_stats.eth_pbuf_alloc_delayed==2) {}
cb->next_p=NULL;
struct NOMEM_CALLBACK* nopbuf_queue_prev=(struct NOMEM_CALLBACK*)eth_pbuf_ctrl->pool->nopbuf_q_end;
if (nopbuf_queue_prev) nopbuf_queue_prev->next_p=cb; else eth_pbuf_ctrl->pool->nopbuf_q_begin=cb;
eth_pbuf_ctrl->pool->nopbuf_q_end=cb;
cb->wait_active=1;
}
else eth_mem_stats.eth_pbuf_alloc_fails++;
return NULL;
}
eth_pbuf_ctrl->free_chain=(struct ETH_PBUF*)p->pbuf.next;
eth_pbuf_ctrl->used++;
if (eth_pbuf_ctrl->used>eth_pbuf_ctrl->used_max) eth_pbuf_ctrl->used_max=eth_pbuf_ctrl->used;
p->pbuf.next=NULL;
int pbuf_num=(p-&eth_pbuf[0]);
return p;
}
struct ETH_PBUF* eth_pbuf_alloc(struct ETH_PBUF_CTRL* eth_pbuf_ctrl, struct NOMEM_CALLBACK* cb) {
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
struct ETH_PBUF* p=do_eth_pbuf_alloc(eth_pbuf_ctrl, cb);
ETH_MEM_UNPROTECT();
if (cb) {
if (p==NULL) {
TNotifyAdd(&eth_pbuf_ctrl->pool->tNotifyHandle, taskNOTIFY_NEW_P_REQUEST);
return NULL;
}
p->pbuf.if_idx = cb->src_interface_id;
}
else p->pbuf.if_idx=0;
p->pbuf.ref=1;
p->pbuf.type_internal=0;// payload directly follows the struct pbuf
p->pbuf.flags=PBUF_FLAG_IS_CUSTOM;// bufer have custom free function
p->pbuf.payload=p->default_payload;
return p;
}
static struct ETH_QUEUEPOOL_CTRL* xpool;
// добавить мост. выделяем пул для пакетных буферов моста, память для интерфейсов
void eth_router_add_bridge(struct ETH_QUEUEPOOL_CTRL* pool, struct ETH_QUEUE* eth_q, uint32_t pool_mem_size_blocks,
struct ETH_PBUF_CTRL* eth_pbuf_ctrl, struct ETH_PBUF* eth_pbuf, uint8_t* eth_pbuf_mem, uint32_t eth_pbufs_cnt,
struct ETH_NETIF* netif_arr, uint32_t netif_count) {
// pbufs init
eth_pbuf_ctrl->free_chain=eth_pbuf;
eth_pbuf_ctrl->pool=pool;
for (int i=0; i<eth_pbufs_cnt; i++) {// initialize all PBUFs
eth_pbuf[i].default_payload=&eth_pbuf_mem[i*ETH_MEM_BUF_SIZE];// link PBUF with memory chunk (in separate space)
eth_pbuf[i].pbuf.type_internal=0;// payload directly follows the struct pbuf
eth_pbuf[i].pbuf.flags=PBUF_FLAG_IS_CUSTOM;// bufer have custom free function
eth_pbuf[i].pbuf.ref=0;// reference count (1 - first allocate)
eth_pbuf[i].pbuf.if_idx=0;// network interface index (0 = no index)
eth_pbuf[i].src_if=0;// network interface index (0 = no index)
eth_pbuf[i].custom_free_function=&eth_custom_pbuf_free_request;// pointer to custom free function
eth_pbuf[i].ctrl=eth_pbuf_ctrl;// link for fast navigate to PBUF control structure
}
for (int i=0; i<eth_pbufs_cnt-1; i++) {// chain all PBUFs (allocation in future get PBUF from this chain)
eth_pbuf[i].pbuf.next=(struct pbuf*)&eth_pbuf[i+1];
}
eth_pbuf[eth_pbufs_cnt-1].pbuf.next=NULL;
// pool init
for (int i=0; i<pool_mem_size_blocks-1; i++) eth_q[i].next=&eth_q[i+1];// chain all free queue control structs for future allocation
eth_q[pool_mem_size_blocks-1].next=NULL;// нужно только в случае переинициализации пула
pool->used=0;// выделено блоков (статистика)
pool->used_max=0;// пик выделения (статистика)
pool->q_begin=eth_q;
pool->eth_netif_array=netif_arr;
pool->eth_netif_size=netif_count;
for (int i=0; i<netif_count; i++) {
netif_arr[i].q_output_end=NULL;
netif_arr[i].q_output_begin=NULL;
netif_arr[i].q_output_len=0;
netif_arr[i].q_output_len_max=0;
netif_arr[i].q_output_size=1;
netif_arr[i].callback_fn=NULL;
netif_arr[i].q_update_cbk=NULL;
netif_arr[i].pool=pool;
netif_arr[i].eth_netif_id=i;
netif_arr[i].if_up=0;
netif_arr[i].callback_pending=0;
}
for (int i=0; i<pool_mem_size_blocks; i++) {// проинициализируем заранее поля буферов один раз, чтобы не обновлять при каждой аллокации
eth_q[i].state=st_free;
eth_q[i].pool=pool;
}
xpool=pool;
}
void eth_router_start_task(struct ETH_QUEUEPOOL_CTRL* pool) {
sem_init(&eth_mem_sem, 0, 1);
TNotifyCreate(&pool->tNotifyHandle);
TaskCreate (EthQueueTask, &pool->pThr);
}
static void eth_custom_pbuf_free_request(struct pbuf* p) {// callback from LWIP pbuf
p->ref=1;// lwip уже декрементировал ref. Чтобы нам корректно освободить, нужно ref вернуть.
eth_pbuf_free_request((struct ETH_PBUF*)p);
}
void eth_pbuf_free_request(struct ETH_PBUF* xpbuf) {// добавлене в очередь на освобождение блока (или передачу другому владельцу)
struct ETH_QUEUEPOOL_CTRL* pool=xpbuf->ctrl->pool;
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
if (xpbuf->pbuf.ref>1) {
xpbuf->pbuf.ref--;
ETH_MEM_UNPROTECT();
return;
}
if (xpbuf->pbuf.ref==0) EM_ASSERT(1);// already free?
int pbuf_num=(xpbuf-&eth_pbuf[0]);
xpbuf->pbuf.next=NULL;//this pbuf must be last in chain
if (pool->free_pbuf_q_end) {// pbuf is not empty
if (pool->free_pbuf_q_end->pbuf.next) EM_ASSERT(2);// ASSERT: invalid pointer to last pbuf. last pbuf not marked as last in chain
pool->free_pbuf_q_end->pbuf.next=&xpbuf->pbuf;// add to end of chain
} else pool->free_pbuf_q_begin=xpbuf;
pool->free_pbuf_q_end=xpbuf;
ETH_MEM_UNPROTECT();
TNotifyAdd(&pool->tNotifyHandle, taskNOTIFY_NEW_FREE_P_REQUEST);
}
static void free_blk(struct ETH_QUEUEPOOL_CTRL* pool) {// освободим блоки из очереди на освобождение
while (1) {
// взятие освобождаемого ETH_PBUF из очереди
struct ETH_PBUF* xpbuf=(struct ETH_PBUF*)pool->free_pbuf_q_begin;// pbuf в начале очереди
if (xpbuf==NULL) { /*ETH_MEM_UNPROTECT();*/ break; }
if (xpbuf->pbuf.ref!=1) EM_ASSERT(3);// ASSERT: invalid allocation counter
int src_if=xpbuf->src_if;
xpbuf->src_if=0;
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
pool->eth_netif_array[src_if].input_queue_len--;
struct ETH_PBUF* n=(struct ETH_PBUF*)xpbuf->pbuf.next;// кто следующий в очереди
pool->free_pbuf_q_begin=n;// продвигаем очередь
if (n==NULL) pool->free_pbuf_q_end=NULL;// если очередь пуста
// действие с освобождаемым ETH_PBUF (освобождение или передача)
if (pool->nopbuf_q_begin) {// pass memory to new owner directly
struct NOMEM_CALLBACK* cb=(struct NOMEM_CALLBACK*)pool->nopbuf_q_begin;
pool->nopbuf_q_begin=cb->next_p;
if (pool->nopbuf_q_begin==NULL) pool->nopbuf_q_end=NULL;
cb->wait_active=0;
ETH_MEM_UNPROTECT();
cb->next_p=NULL;// на всякий случай, в принципе это не нужно
eth_mem_stats.eth_pbuf_alloc_delay_cbks++;
xpbuf->pbuf.if_idx = cb->src_interface_id;
cb->callback_fn(xpbuf, cb);// нужно выделить только pbuf
}
else {// free memory
xpbuf->pbuf.next=(struct pbuf*)xpbuf->ctrl->free_chain;// освобождаемый блок добавляем в начало очереди
xpbuf->ctrl->free_chain=xpbuf;
xpbuf->pbuf.ref=0;// для порядка. в продакшене не требуется
if (xpbuf->ctrl->used==0) EM_ASSERT(4);
xpbuf->ctrl->used--;
ETH_MEM_UNPROTECT();
}
if (pool->eth_netif_array[src_if].q_update_cbk) pool->eth_netif_array[src_if].q_update_cbk(&pool->eth_netif_array[src_if]);// вызовем callback, что очередь стала меньше
}
}
// Процесс, обслуживающий:
// - очередь запросов на освобождение памяти
// - очередь коллбэков на выделение памяти (тем кто в очереди на получение памяти при дефиците памяти)
// - очередь пакетов на роутинг
static void EthQueueTask(void* arg) {
struct ETH_QUEUEPOOL_CTRL* pool=xpool;
while (1) {
uint32_t res=TNotifyWait(&pool->tNotifyHandle);
if (res & taskNOTIFY_NEW_FREE_P_REQUEST) {// new pbuf_free requests
free_blk(pool);
}
if (res & taskNOTIFY_ROUTER_Q_UPDATE) {// new dgram in queue
while (1) {
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
struct ETH_QUEUE* queue=(struct ETH_QUEUE*)pool->q_input_begin;
if (queue==NULL) { ETH_MEM_UNPROTECT(); break; }
struct ETH_QUEUE* n=queue->next;
pool->q_input_begin=n;// забираем из очереди
if (n==NULL) pool->q_input_end=NULL;
queue->next=NULL;
pool->q_input_used--;
ETH_MEM_UNPROTECT();
eth_route_block(queue);// и отдаём в роутинг
if (pool->free_pbuf_q_begin) free_blk(pool);
}
}
}
}
// Выделить блок памяти.
inline static struct ETH_QUEUE* do_eth_queue_entry_alloc(struct ETH_QUEUEPOOL_CTRL* pool) {
struct ETH_QUEUE* queue = (struct ETH_QUEUE*)pool->q_begin;// try to allocate queue
if (queue==NULL) {
pool->alloc_fails++;
eth_mem_stats.qpool_alloc_fails++;
return NULL;
}
pool->q_begin = queue->next;// update pointer to next free queue
pool->used++;
if (pool->used_max < pool->used) pool->used_max = pool->used;
queue->state = st_allocated;
return queue;// allocated memory
}
static struct ETH_QUEUE* eth_queue_entry_alloc(struct ETH_QUEUEPOOL_CTRL* pool) {
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
struct ETH_QUEUE* q=do_eth_queue_entry_alloc(pool);
ETH_MEM_UNPROTECT();
return q;
}
void eth_queue_entry_free(struct ETH_QUEUE* queue) {// освобождение элемента очереди
struct ETH_QUEUEPOOL_CTRL* pool=queue->pool;
if (queue->state==st_free) EM_ASSERT(5);// ASSERT: trying to free not used queue
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
queue->state=st_free;
queue->next=(struct ETH_QUEUE*)pool->q_begin;// освобождаемый блок добавляем в начало очереди
pool->q_begin=queue;
pool->used--;
ETH_MEM_UNPROTECT();
}
#pragma optimize=none
void eth_add_packet_to_router_queue(struct ETH_PBUF* xpbuf) {
uint32_t nif=xpbuf->pbuf.if_idx;
if (xpbuf->pbuf.ref==0) EM_ASSERT(11);
if (nif>=ETH_NETIFS) EM_ASSERT(6);//
xpbuf->src_if=nif;
if (xpbuf->pbuf.len<14) {// invalid datagram. 14 bytes (src mac+dst mac + ethertype) required
eth_pbuf_free_request(xpbuf);
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
xpbuf->ctrl->pool->eth_netif_array[nif].dgrams_lost++;
ETH_MEM_UNPROTECT();
return;
}
struct ETH_QUEUEPOOL_CTRL* pool=xpbuf->ctrl->pool;
struct ETH_QUEUE* queue=eth_queue_entry_alloc(pool);
if (queue==NULL) {
eth_pbuf_free_request(xpbuf);
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
pool->eth_netif_array[nif].dgrams_lost++;
ETH_MEM_UNPROTECT();
return;
}
queue->next = NULL;
queue->state = st_in_queue;
queue->pbuf = xpbuf;
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
pool->eth_netif_array[nif].input_queue_len++;
pool->eth_netif_array[nif].dgrams_in++;
if (pool->q_input_end!=NULL) pool->q_input_end->next=queue; else pool->q_input_begin=queue;
pool->q_input_end=queue;
pool->q_input_used++;
if (pool->q_input_used_max<pool->q_input_used) pool->q_input_used_max=pool->q_input_used;
ETH_MEM_UNPROTECT();
TNotifyAdd(&pool->tNotifyHandle, taskNOTIFY_ROUTER_Q_UPDATE);
}
struct ETH_PBUF* eth_get_packet(struct ETH_NETIF* enetif) {// запрос пакета из исходящей очереди драйвером для передачи во внешний мир
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
struct ETH_QUEUE* queue=(struct ETH_QUEUE*)enetif->q_output_begin;
if (queue) {// packet ready
struct ETH_QUEUE* next_queue=queue->next;
enetif->q_output_begin=next_queue;
if (next_queue == NULL) enetif->q_output_end = NULL;
if (enetif->q_output_len==0) EM_ASSERT(7);// ASSERT: сбой подсчета размера очереди.
enetif->q_output_len--;
enetif->dgrams_out++;
ETH_MEM_UNPROTECT();
queue->next=NULL;
queue->state=st_sending;
struct ETH_PBUF* xpbuf=queue->pbuf;
eth_queue_entry_free(queue);
return xpbuf;
}
if (enetif->callback_fn) enetif->callback_pending=1;
ETH_MEM_UNPROTECT();
return NULL;
}
void eth_add_packet_to_output_queue(struct ETH_QUEUE* queue, struct ETH_NETIF* enetif) {// для роутера. отправить в исходящую очередь нужного интерфейса (или передать сразу драйверу, если он ждёт пакет)
queue->next = NULL;
if (queue->pbuf->pbuf.ref==0) EM_ASSERT(8);
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
if (enetif->callback_pending) {// интерфейс ожидает блок - отправляем сразу в интерфейс без очереди
if (enetif->q_output_end) EM_ASSERT(9);// assert: драйвер ждёт пакет, но в очереди почему-то что-то есть. Хотя должно быть пусто...
enetif->callback_pending=0;
queue->state = st_sending;
enetif->dgrams_out++;
ETH_MEM_UNPROTECT();
struct ETH_PBUF* xpbuf=queue->pbuf;
eth_queue_entry_free(queue);
if (enetif->callback_fn) enetif->callback_fn(xpbuf, enetif);
else EM_ASSERT(10);// no callback
return;
}
if (enetif->q_output_len>=enetif->q_output_len_max) {// очередь уже полна. дропаем пакет.
enetif->dgrams_lost++;
ETH_MEM_UNPROTECT();
eth_pbuf_free_request(queue->pbuf);
eth_queue_entry_free(queue);
return;
}
queue->state = st_in_queue;// добавляем в очередь
if (enetif->q_output_end) enetif->q_output_end->next=queue; else enetif->q_output_begin=queue;// этот элемент приписываем к концу очереди
enetif->q_output_end=queue;// конечным элементом ставим этот элемент
enetif->q_output_len++;
if (enetif->q_output_len_max<enetif->q_output_len) enetif->q_output_len_max=enetif->q_output_len;
ETH_MEM_UNPROTECT();
}
struct ETH_QUEUE* eth_mem_clone(struct ETH_QUEUE* queue) {
struct ETH_QUEUE* queue_copy=eth_queue_entry_alloc(queue->pool);
if (queue_copy) {
queue_copy->pbuf=queue->pbuf;
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
queue->pbuf->pbuf.ref++;
ETH_MEM_UNPROTECT();
}
return queue_copy;
}
+234
View File
@@ -0,0 +1,234 @@
#pragma once
#include <semaphore.h>
#include "xlib.h"
#include "eth_router_cfg.h"
#include "lwip/pbuf.h"
/* Менеджер памяти и очередей для ethernet пакетов.
Умеет:
- выделять и освобождать память из пулов (пока пул один, но архитектурно заложена возможность использования нескольких пулов)
- при ошибке выделения памяти вызвать callback как только память появилась (т.е. как только кто-то освободил)
- работать с очередями: помещать пакеты из всех интерфейсов в общую очередь на роутинг (из irq или потока)
Менеджер содержит в себе поток, обслуживающий нужды очереди менеджера памяти и очередь на роутинг. Из этого потока вызываются все коллбэки.
Коллбэки могут заниматься среднезатратными по времени вещами (например, копирование всего пакета или подсчет CRC всего пакета), но не могут вставать в ожидание чего-либо.
Ожидание коллбэков будет тормозить обработку входящих очередей с интерфейсов и очереди на операции с памятью.
Роутер из очереди на роутинг распихивает пакеты в интерфейсы назначения. Если при попытке запихнуть пакет в интерфейс назначения размер очередь этого интерфейса заполнена, пакет отбрасывается.
Для броадкастов роутером создаются копии пакета на каждый исходящий интерфейс. Ибо нужно каждую копию запихнуть в свою очередь, а очередь у пакета только одна.
Рекомендуемый размер входящих очередей - 2 пакета: один в процессе приёма, второй в потоке роутера.
Пакеты во входящих очередях обрабатываются сразу (как это позволть сделать приоритет потока обработчика).
Размер исходящих очередей должен быть больше, его задача удерживать в буферах всё что вовремя не пролезает через медленные интерфейсы.
Пока пакет не фрагментируется. Всё что не влезает в размер одного буфера (ETH_MEM_BUF_SIZE), отбрасывается.
Рекомендации по драйверам интерфейсов:
- при инициализации:
eth_netif_array[YOUR_NETIF_ID].q_output_len_max=<размер очереди на передачу в пакетах>
eth_netif_array[YOUR_NETIF_ID].callback_fn=lwip_callback_from_bridge;// инициализируем callback (пакет готов)
eth_netif_array[ETH_NETIF_ID].if_up=1;// интерфейс готов принимать пакеты
- выделить память из пула перед приёмом пакета (т.е. буфера резервируются когда инициализируются буфера приёма), и записывать пакет сразу в эту память.
- если при инициализации буфера был отказ в выделении памяти, ждать коллбэк. Когда прилетит callback, можно инициализировать буфер и запускать приём.
Передача:
1. инициализируем callback на новый пакет.
2. запрашиваем пакет (eth_get_packet). Функция либо возвратит что есть в очереди, либо активирует коллбэк. В этом случае ждем пакет.
3. когда пакет получен, передаем пакет
4. повторяем начиная с пп.2
Обработчик коллбэка вызывается один раз после того как eth_get_packet вернул NULL (т.е. отсутствие пакета)
*/
// параметры инициализации пула по умолчанию:
extern sem_t eth_mem_sem;
#define ETH_MEM_ALIGN __attribute__((aligned(4)))// для CPU без кеша
#define ETH_MEM_DECL_PROTECT()
#define ETH_MEM_PROTECT() {sem_wait(&eth_mem_sem); /*asm("DSB SY");*/}
#define ETH_MEM_UNPROTECT() {/*asm("DSB SY");*/ sem_post(&eth_mem_sem);}
#define EM_ASSERT(x) {dbg[10]=x; while(1);}
// ======================== Управляющие структуры =============
struct ETH_PBUF_CTRL {
volatile struct ETH_PBUF* free_chain;// linked-list для размещения-освобождения буферов
volatile uint32_t used;// счетчик, сколько сейчас элементов занято
uint32_t used_max;// сколько было занято максимум
struct ETH_QUEUEPOOL_CTRL* pool;
};
#ifndef PBUF_FLAG_IS_CUSTOM// cleck for LWIP pbuf is included
#define PBUF_FLAG_IS_CUSTOM 0x02U
struct pbuf {
struct pbuf *next; // next fragment in chain (NULL - end of packet)
void *payload; // memory for packet payload
uint16_t tot_len; // remain packet length from begin of this part
uint16_t len; // this fragment length
uint8_t type_internal; // payload directly follows the struct pbuf
uint8_t flags; // PBUF_FLAG_IS_CUSTOM
uint8_t ref; // reference count
uint8_t if_idx; // network interface index
};
typedef void (*pbuf_free_custom_fn)(struct pbuf *p);
#endif
struct ETH_PBUF {
struct pbuf pbuf;
// struct pbuf: *next // next fragment in chain (NULL - end of packet)
// void *payload; // memory for packet payload
// u16_t tot_len; // remain packet length from begin of this part
// u16_t len; // this fragment length
// u8_t type_internal; // payload directly follows the struct pbuf
// u8_t flags; // PBUF_FLAG_IS_CUSTOM
// LWIP_PBUF_REF_T ref; // reference count
// u8_t if_idx; // network interface index
// pbuf_free_custom_fn // custom pbuf free function
pbuf_free_custom_fn custom_free_function;
uint8_t* default_payload;
uint8_t src_if;
struct ETH_PBUF_CTRL* ctrl;
};
struct ETH_QUEUE {// ячейка пула
struct ETH_QUEUE* next;// указатель на следующий элемент списка (очереди, которая определяется параметром mia_state)
struct ETH_QUEUEPOOL_CTRL* pool;
struct ETH_PBUF* pbuf;// Обращаться к ETH_PBUF / pbuf нужно через этот указатель!
volatile enum {
st_free=0,// ячейка свободна, поле next указывает на следующую свободную ячейку, т.е. используется дл выделения памяти
st_allocated=1,// ячейка занята, идёт процесс записи данных в ячейку, поле next не используется
st_in_queue=2,// ячейка в очереди на обработку, поле next указывает на следующую ячейку в данной очереди
st_sending=3,// в процессе отправки на интерфейсе назначения
st_free_pending=4 } state;// ячейка в очереди на освобождение (или передачи другому ожидающему память владельцу), поле next указывает на следующий элемент очереди на совобождение
uint8_t dst_if_idx;// если 0 - то роутится роутером. Если не 0, то роутится в соответствующиё исходящий интерфейс
};
struct ETH_MEM_STATS {
uint32_t qpool_alloc_fails;// queue entry alloc fail (summary, for all queues)
uint32_t eth_pbuf_alloc_fails;
uint32_t eth_pbuf_alloc_delayed;
uint32_t eth_pbuf_alloc_delay_cbks;
};
extern struct ETH_MEM_STATS eth_mem_stats;
struct NOMEM_CALLBACK {// структура для организации очереди коллбэков на выделение памяти для входящих пакетов, т.е. принимаемых драйвером (экземпляры структуры создаются интерфейсом)
void (*callback_fn)(struct ETH_PBUF*, struct NOMEM_CALLBACK*);
struct NOMEM_CALLBACK* next_p;// chain for pbuf allocation requests
struct ETH_PBUF* p;
uint8_t src_interface_id;
uint8_t wait_active;// Если в состоянии ожидания выдачи памяти - то =1
};
struct ETH_NETIF {// сетевой интерфейс (элемент netif_list). определа в виде массива элементов заранее определенного размера, индекс является номером интерфейса и eth_netif_id.
volatile struct ETH_QUEUE* q_output_end;// сюда добавляем пакет после роутинга
volatile struct ETH_QUEUE* q_output_begin;// забираем пакет драйвером интерфейса
volatile uint32_t q_output_len; // размер исходящей очереди
volatile uint32_t q_output_len_max; // фиксируем пик очереди
volatile uint32_t q_output_size; // максимальный размер исходящей очереди. Количество элементов в пуле должно хватать для обслуживания всех очередей.
// входящая очередь не лимитируется (предполагается, что пакет во входящей очереди не задерждится надолго и быстро улетит в исходящую, либо отбросится если исходящая очередь пепеполнена).
void (*callback_fn)(struct ETH_PBUF*, struct ETH_NETIF*);// callback готовности пакета на передачу драйверу
struct ETH_QUEUEPOOL_CTRL* pool;// пул памяти, использующийся этим интерфейсом
void (*q_update_cbk)(struct ETH_NETIF*);// callback уменьшения кол-ва пакетов в ожидании обработки от этого интерфейса
uint8_t eth_netif_id;// ID интерфейса. всегда является индексом eth_netif_array. сделан для ускорения определения индекса по указателю.
volatile uint8_t if_up;// интерфейс включен (если 0, то интерфейс не используется для передачи-приема пакетов)
volatile uint8_t callback_pending;// ждём callback
uint32_t dgrams_in;
uint32_t dgrams_out;
uint32_t dgrams_lost;
uint32_t input_queue_len;// размер очереди кодограмм от этого интерфейса
char* if_name;
};
struct ETH_QUEUEPOOL_CTRL {// описание пула элементов для интерфейса моста
volatile struct ETH_QUEUE* q_begin;// начало списка свободных буферов. Сюда и добавляем освобождаемую память, и забираем при размещении (т.е. работает как стек)
volatile struct NOMEM_CALLBACK* nopbuf_q_end;// сюда добавляем / очередь желающих получить pbuf
volatile struct NOMEM_CALLBACK* nopbuf_q_begin;// отсюда забираем
volatile struct ETH_PBUF* free_pbuf_q_end;// добавляем - очередь запросов на освобождение блока
volatile struct ETH_PBUF* free_pbuf_q_begin;// забираем
volatile struct ETH_QUEUE* q_input_end;// добавляем - очередь входящих пакетов на роутинг
volatile struct ETH_QUEUE* q_input_begin;// забираем
volatile uint32_t q_input_used;// счетчик, сколько сейчас элементов входящей очереди занято
volatile uint32_t q_input_used_max;// пик
volatile uint32_t used;// счетчик, сколько сейчас элементов пула занято
uint32_t used_max;// сколько было занято максимум
volatile uint32_t alloc_fails;// счетчик ошибок выделения
struct ETH_NETIF* eth_netif_array;// массив структур описывающих подключенные сетевые интерфейсы
struct NHandle_t tNotifyHandle;// процесс, обслуживающий этот пул
pthread_t pThr;
uint8_t eth_netif_size;// количество элементов структуры eth_netif_array
};
// ======================== API =============
// проинициализировать мост:
// - кастомный пул памяти (pool - управляющая структура, pool_mem - структура блоков памяти для пула, pool_mem_size_blocks - количество блоков памяти)
// - пул очередей
// не thread-safe. пул можно переинициализировать в любой момент. Пока не завершена (пере)инициализация нельзя пользоваться функциями работы с пулом.
// т.е. сперва инициализируем пул, потом запускаем периферию интерфейсов.
void eth_router_add_bridge(struct ETH_QUEUEPOOL_CTRL* pool, struct ETH_QUEUE* eth_q, uint32_t pool_mem_size_blocks,
struct ETH_PBUF_CTRL* eth_pbuf_ctrl, struct ETH_PBUF* eth_pbuf, uint8_t* eth_pbuf_mem, uint32_t eth_pbufs_cnt,
struct ETH_NETIF* netif_arr, uint32_t netif_count);
void eth_router_start_task(struct ETH_QUEUEPOOL_CTRL* pool);
// Внутренняя функция
// выделить элемент очереди из пула pool (thread/irq safe, если настроено выше)
//struct ETH_QUEUE* eth_queue_entry_alloc(struct ETH_QUEUEPOOL_CTRL* pool);
// Функция для роутера
// Освобождаем блок (thread/irq safe, если настроено выше).
// Блок должен быть выделен из любого пула ETH_QUEUE.
void eth_queue_entry_free(struct ETH_QUEUE* q);
// Запрос пакета драйвером интерфейса из очереди (thread/irq safe, если настроено выше)
// Если пакет есть в очереди на передачу, пакет извлекается из очереди и указатель на него возвращается функцией.
// Драйвер должен передать пакет, затем освободить буфер.
// Если в очереди пусто, функция возвращает NULL и инициирует ожидание пакета в очереди. Как только в очереди появится новый пакет, будет вызван callback, описанный в структуре enetif.
// В вызове callback будет указатель на пакет и указатель на сетевой интерфейс.
// в enetif предварительно надо проинициализировать:
// callback_fn - указатель на callback-функцию;
struct ETH_PBUF* eth_get_packet(struct ETH_NETIF* enetif);
// Функция для драйвера сетевого интерфейса
// отправить принятый интерфейсом пакет в роутер (thread/irq safe, если настроено выше)
// перед этим вызовом предполагается что память была выделена функцией eth_pbuf_alloc, пакет записан в память pbuf->payload и в pbuf->if_idx вписан номер интерфейса.
// размер доступной памяти payload в байтах равен ETH_MEM_BUF_SIZE
void eth_add_packet_to_router_queue(struct ETH_PBUF* pbuf);
// Функция для роутера
// отправить пакет "block" в очередь исходящую очередь интерфейса "enetif" (только из потока роутера).
// либо если драйвер ждёт пакет, педедать его сразу, минуя очередь
void eth_add_packet_to_output_queue(struct ETH_QUEUE* queue, struct ETH_NETIF* enetif);
// Функция для роутера
// дублирует пакет и создает новую очередь для пакета.
// память пакета для всех копий общая. Поэтому изменеять содержимое пакета после клонирования нельзя.
// используется для броадкастов (отправка копии пакета на все интерфйесы)
struct ETH_QUEUE* eth_mem_clone(struct ETH_QUEUE* block);
// выделяет pbuf. Если указан CB, то при ошибке выделения как только появится свободный ETH_PBUF, будет вызван callback с этим ETH_PBUF
// Для активации CB нужен заранее проинициализированный экземпляр структуры callback.
// Если предполагается очередь из нескольких callback-ов на отказ памяти, то для всех callback-ов, которые одновременно могут находиться в очереди, нужен отдельный экземпляр структуры.
// Рекомендуется при первом отказе памяти перестать размещать новые блоки и дождаться callback-а. В коллбэке можно пытаться дальше выделять память до первой ошибки.
// в cb предварительно надо проинициализировать:
// callback_fn - указатель на callback-функцию;
// src_interface_id - номер интерфейса (он проинициализируется в pbuf). Также можно использовать для определения экземпляра драйвера (если один обработчик на несколько интерфейсов)
// Нумерация интерфейсов - от единицы. 0 означает "не проинициализировано". Драйвер должен установить корректно номер интерфейса, иначе будут проблемы с роутингом.
// если cb=NULL, то номер интерфейса нужно будет проинициализировать самостоятельно после выделения блока.
struct ETH_PBUF* eth_pbuf_alloc(struct ETH_PBUF_CTRL* eth_pbuf_ctrl, struct NOMEM_CALLBACK* cb);
// Освобождаем блок (thread/irq safe, если настроено выше).
// Блок должен быть выделен из любого пула ETH_PBUF.
void eth_pbuf_free_request(struct ETH_PBUF* pbuf);
+489
View File
@@ -0,0 +1,489 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <strings.h>
#include <errno.h>
#include "lwip/opt.h"
#include "lwip/tcp.h"
#include "lwip/udp.h"
#include "lwip/mem.h"
#include "dnsproxy.h"
#include "eth_router.h"
#include "eth_queue.h"
#include "lwip/lwip.h"
#include "eth_nat.h"
#include "linux/tcp.h"
#define PROT_TCP 6
#define PROT_UDP 17
#define PROT_ICMP 1
#define NAT_DIVERT_PORT 1234
pthread_t tnatHandle;
pthread_t tnatRXHandle;
//static struct NHandle_t tNotifyHandle;
#define taskNOTIFY_NEW_DATA 1
// src ip:port / dst ip:port -> src ip/port / dst <- divert ip:port
// В пакете подменяется dst ip:port, и в таблицу nat пишется соответствие src ip:port к dst ip:port
struct NAT_TAB nattab[NAT_TAB_SIZE];
struct NAT_STAT nat_stat;
static int nat_task_pipe[2];
static int nat_rx_task_pipe[2];
_Noreturn static void calc_stats(void * arg) {
while(1) {
int nofl_conn = 0;
for (int i = 0; i < NAT_TAB_SIZE; i++) {
int didx=nattab[i].index_end-nattab[i].index_begin;
if (didx<0) didx+=SNDQ_MAXLEN;
nofl_conn+=didx;
// if (nattab[i].index_begin != nattab[i].index_end) nofl_conn++;
}
nat_stat.lw_conn_used = nofl_conn;
usleep(10000);
}
}
int forward_nat(struct ETH_QUEUE* block) {// пакет в интернет - заворачивается на локальный ip/port по таблице соответствий
struct ETH_PKT_HDR* pkt=(struct ETH_PKT_HDR*)block->pbuf->pbuf.payload;
if (pkt->ethertype!=htons(0x800)) return -1;// no match
if (pkt->ip_dst==0xffffffff) return -1;//broadcast
if ((gnetif.ip_addr.addr & gnetif.netmask.addr) == (pkt->ip_dst & gnetif.netmask.addr) ) return -1;// local dgram
if (pkt->proto!=PROT_TCP && pkt->proto!=PROT_UDP/* && pkt->proto!=PROT_ICMP*/) return -1;
uint32_t curtime=xTaskGetTickCount();
uint8_t* ip=&pkt->ip_src;
uint16_t port=htons(pkt->port_src);
uint8_t* dip=&pkt->ip_dst;
uint16_t dport=htons(pkt->port_dst);
int nat_entry=-1;
for (int i=0; i<NAT_TAB_SIZE; i++) {
// if (pkt->proto==PROT_TCP || pkt->proto==PROT_UDP) {
if (pkt->ip_src == nattab[i].src_ip &&
pkt->ip_dst==nattab[i].dst_ip &&
pkt->port_src==nattab[i].src_port &&
pkt->port_dst==nattab[i].dst_port &&
nattab[i].proto==pkt->proto ) { /*print_log("[NAT_TCP] Found match...");*/ nat_entry=i; break;}
// }
}
if (nat_entry==-1) {// find oldest entry
int oldent=0;
uint32_t maxtime=0;
for (int i=0; i<NAT_TAB_SIZE; i++) {
if (nattab[i].status) continue;// не трогаем не разорванные TCP соединения
if (curtime-nattab[i].time>maxtime) { maxtime=curtime-nattab[i].time; oldent=i; }
}
nat_entry=oldent;
nattab[nat_entry].src_ip=pkt->ip_src;
nattab[nat_entry].dst_ip=pkt->ip_dst;
nattab[nat_entry].src_port=pkt->port_src;
nattab[nat_entry].dst_port=pkt->port_dst;
nattab[nat_entry].proto=pkt->proto;
}
nattab[nat_entry].time=curtime;
pkt->ip_dst=gnetif.ip_addr.addr;
pkt->port_dst=htons(NAT_DIVERT_PORT);
// print_log("[NAT_TCP] === forward pkt from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d nat_entry %d proto %d", ip[0],ip[1],ip[2],ip[3], port, dip[0],dip[1],dip[2],dip[3], dport, nat_entry, pkt->proto);
return 0;
}
int backward_nat(struct ETH_QUEUE* block) {// пакет из интернета (т.е. LWIP стека) в локалку
struct ETH_PKT_HDR *pkt = (struct ETH_PKT_HDR *) block->pbuf->pbuf.payload;
if (pkt->ethertype != htons(0x800)) return -1;// no match
if (pkt->ip_src != gnetif.ip_addr.addr && pkt->port_src != htons(NAT_DIVERT_PORT))
return -1;// local dgram
if (pkt->proto != PROT_TCP && pkt->proto != PROT_UDP && pkt->proto != PROT_ICMP) return -1;
uint32_t curtime = xTaskGetTickCount();
int nat_entry = -1;
for (int i = 0; i < NAT_TAB_SIZE; i++) {
if (pkt->ip_dst == nattab[i].src_ip && pkt->port_dst == nattab[i].src_port &&
pkt->proto == nattab[i].proto) {
nat_entry = i;
break;
}
}
if (nat_entry == -1) return -1;// no match
pkt->ip_src = nattab[nat_entry].dst_ip;
pkt->port_src = nattab[nat_entry].dst_port;
uint8_t* ip=&pkt->ip_src;
uint16_t port=htons(pkt->port_src);
uint8_t* dip=&pkt->ip_dst;
uint16_t dport=htons(pkt->port_dst);
// print_log("[NAT_TCP] === backward pkt from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d nat_entry %d proto %d", ip[0],ip[1],ip[2],ip[3], port, dip[0],dip[1],dip[2],dip[3], dport, nat_entry, pkt->proto);
return 0;
}
struct tcp_pcb* nat_tcp;
static void nat_close_so_conn(uint32_t idx) {
if (nattab[idx].status) {
shutdown(nattab[idx].socket, SHUT_RDWR);
nattab[idx].status=0;
}
// if (nattab[idx].status) { close(nattab[idx].socket); nattab[idx].status=0;}
}
static void nat_close_lw_conn(uint32_t idx) {
if (nattab[idx].pcb) {
uint32_t ptr=nattab[idx].index_begin;
while (ptr!=nattab[idx].index_end) {
if (nattab[idx].p[ptr]) {
tcp_recved(nattab[idx].pcb, nattab[idx].p[ptr]->tot_len);
pbuf_free(nattab[idx].p[ptr]);
nat_stat.pbuf_used--;
nattab[idx].p[ptr]=NULL;
}
ptr++;
if (ptr>=SNDQ_MAXLEN) ptr=0;
}
nattab[idx].offs=0;
nattab[idx].index_begin=ptr;
nat_stat.tcp_close++;
err_t e=tcp_shutdown(nattab[idx].pcb, 1, 1);
if (e==ERR_OK) {
tcp_abort(nattab[idx].pcb);
nattab[idx].pcb=NULL;
}
nattab[idx].pcb=NULL;
}
nattab[idx].txbuf_len=0;
}
_Noreturn static void NAT_Task( void* arg ) {// здесь обслуживаем передачу из LWIP в сокет
uint32_t sel_req=0;
LOCK_LWIP_CORE();
while (1) {
uint32_t act;
int maxfd=-1;
fd_set wfd;
FD_ZERO(&wfd);
for (int i = 0; i < NAT_TAB_SIZE; i++) {
if (nattab[i].status>0 ) {// descriptor is active
if (nattab[i].socket>maxfd) maxfd=nattab[i].socket;
if (nattab[i].index_begin!=nattab[i].index_end) { FD_SET(nattab[i].socket, &wfd); sel_req=1; }
}
}
fd_set rfd;
FD_ZERO(&rfd);
FD_SET(nat_task_pipe[0], &rfd);
if (maxfd<nat_task_pipe[0]) maxfd=nat_task_pipe[0];
UNLOCK_LWIP_CORE();
// struct timeval timeout={0,100*1000};// x0.1s потом ожно добавить еще один локальный сокет чтобы будить (добавить поток)
int res = select(maxfd+1, &rfd, &wfd, NULL, NULL /*&timeout*/);
LOCK_LWIP_CORE();
if (res == -1) continue;
if (FD_ISSET(nat_task_pipe[0], &rfd)) {// new socket
// print_log("[NAT_Task] pipe event");
char dummy;
read(nat_task_pipe[0], &dummy, 1);// recv from socket
}
for (int i = 0; i < NAT_TAB_SIZE; i++) {
if (nattab[i].status==0) continue;// дескриптор куда-то делся
if (FD_ISSET(nattab[i].socket, &wfd)) do {// socket ready for write data
// print_log("[NAT_Task] Write to tab %d", i);
struct pbuf *p=nattab[i].p[nattab[i].index_begin];
struct pbuf *p1=p;
uint32_t offs=nattab[i].offs;
int size=p->tot_len;
while(p1->next!=NULL && offs>=p1->len) {// SEEK to offs into pbuf chain
if (p1->next==NULL && p1->len!=size) { nat_stat.pbuf_broken++; size=p1->len; }
offs-=p1->len; size-=p1->len; p1=p->next;
}
int len=send(nattab[i].socket, (uint8_t*)p1->payload+offs, p->len-offs, MSG_DONTWAIT);
// print_log("[NAT_Task] tab %d send %d:%d bytes, %d sent", i, offs, p->len-offs, len);
if (len<0) {
if (errno == EAGAIN || errno == ENOBUFS) break;//
print_log("[NAT_Task] tab %d send error, close connection (err %d: %s)", i, errno, strerror(errno));
nattab[i].shutdown_req=1;
nat_close_so_conn(i);
nat_close_lw_conn(i);
break;
}
nattab[i].offs+=len;
if (nattab[i].offs<p->tot_len) { sel_req=1; break;}// not all sent
nattab[i].p[nattab[i].index_begin]=0;
nattab[i].index_begin++;
if (nattab[i].index_begin>=SNDQ_MAXLEN) nattab[i].index_begin=0;
nattab[i].offs=0;
tcp_recved(nattab[i].pcb, p->tot_len);
nat_stat.pbuf_used--;
pbuf_free(p);
// print_log("[NAT_Task] tab %d free pbuf", i);
} while(0);
}
}
}
_Noreturn static void NAT_RX_Task( void* arg ) {// здесь обслуживаем прием из сокетов и передачу в LWIP
uint32_t sel_req=0;
LOCK_LWIP_CORE();
while (1) {
uint32_t act;
int maxfd=-1;
fd_set rfd, efd;
FD_ZERO(&rfd); FD_ZERO(&efd);
for (int i = 0; i < NAT_TAB_SIZE; i++) {
if (nattab[i].status>0 ) {// descriptor is active
if (nattab[i].socket>maxfd) maxfd=nattab[i].socket;
FD_SET(nattab[i].socket, &rfd);
FD_SET(nattab[i].socket, &efd);
}
}
FD_SET(nat_rx_task_pipe[0], &rfd);
if (maxfd<nat_rx_task_pipe[0]) maxfd=nat_rx_task_pipe[0];
if (maxfd==-1) {
UNLOCK_LWIP_CORE();
usleep(100*1000);
LOCK_LWIP_CORE();
continue;
}
UNLOCK_LWIP_CORE();
// struct timeval timeout={0,100*1000};// x0.1s потом ожно добавить еще один локальный сокет чтобы будить (добавить поток)
int res = select(maxfd+1, &rfd, NULL, &efd, NULL /*&timeout*/);
LOCK_LWIP_CORE();
if (res == -1) continue;
if (FD_ISSET(nat_rx_task_pipe[0], &rfd)) {// new socket
// print_log("[NAT_rxTask] pipe event");
char dummy;
read(nat_rx_task_pipe[0], &dummy, 1);// recv from socket
}
for (int i = 0; i < NAT_TAB_SIZE; i++) {
if (nattab[i].status==0) continue;// дескриптор куда-то делся
if (FD_ISSET(nattab[i].socket, &efd)) {// error: close connection
print_log("[NAT_rxTask] tab %d select errorfd occurs, close connection (by remote host)", i);
nattab[i].shutdown_req=1;
nat_close_so_conn(i);
nat_close_lw_conn(i);
continue;// отключили сокет
}
if (FD_ISSET(nattab[i].socket, &rfd)) {// socket ready for read data
int rfd_cont=0;
do {
if (nattab[i].txbuf_len <= 0) {
int len = recv(nattab[i].socket, nattab[i].txbuf, sizeof(nattab[0].txbuf), MSG_DONTWAIT);// recv from socket
// print_log("[NAT_rxTask] tab %d recv %d bytes err %d %s", i, len, errno, strerror(errno));
if (len==0 && rfd_cont==0) {// connection shutdown request
print_log("[NAT_rxTask] tab %d shutdown connection", i);
nattab[i].shutdown_req=1;
nat_close_so_conn(i);
nat_close_lw_conn(i);
break;
}
rfd_cont++;
if (len<0) {
if (errno == EAGAIN) break;//
print_log("[NAT_rxTask] tab %d recv error, close connection (err %d: %s)", i, errno, strerror(errno));
nattab[i].shutdown_req=1;
nat_close_so_conn(i);
nat_close_lw_conn(i);
}
if (len < 1) { break; }// error recv data
nattab[i].txbuf_len=len;
}
if (nattab[i].txbuf_len > 0) {
err_t err=tcp_write(nattab[i].pcb, nattab[i].txbuf, nattab[i].txbuf_len, TCP_WRITE_FLAG_COPY);// write to lwip
if (err==ERR_OK) {
nattab[i].txbuf_len=0;
continue;
}
}
break;
} while(1);
}
}
}
}
static void nat_tcp_err(void *arg, err_t err) { // The pcb had an error and is already deallocated. The argument might still be valid (if != NULL).
if (arg) {
uint32_t num=(int)arg-1;
print_log("[NAT_Task] tab %d close connection (by local host)", num);
if (num<NAT_TAB_SIZE) {
nat_close_so_conn(num);
nattab[num].pcb=NULL;
}
}
}
static int nat_find_match(uint32_t ip, uint16_t port, uint8_t proto) {
for (int i = 0; i < NAT_TAB_SIZE; i++) {
if (ip == nattab[i].src_ip && port == nattab[i].src_port && proto == nattab[i].proto) return i;
}
return -1;
}
static err_t nat_tcp_sent(void *arg, struct tcp_pcb *pcb, u16_t len) {// Data has been sent and acknowledged by the remote host. This means that more data can be sent.
// TNotifyAdd( &tNotifyHandle, taskNOTIFY_NEW_DATA);
write(nat_task_pipe[1], "1",1);// notify for new data
return ERR_OK;
}
static err_t nat_tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { // Data has been received on this pcb.
uint32_t nat_entry=(int)arg-1;
if ((err != ERR_OK) || (pcb == NULL) || (p == NULL)) {
print_log("[NAT_LWTCP_RECV1] closing connection by loacl side request: err=%d pcb=%d p=%d", err, pcb, p);
if (nat_entry<NAT_TAB_SIZE) {
nattab[nat_entry].shutdown_req=1;
nat_close_so_conn(nat_entry);
nat_close_lw_conn(nat_entry);
}
return ERR_VAL;
}
uint32_t* ip=&pcb->remote_ip.addr;
uint16_t port=htons(pcb->remote_port);
// print_log("[NAT_LWTCP_RECV3] nat_entry=%d rport=%d %d.%d.%d.%d", nat_entry, htons(port), (*ip)&0xff, (*ip>>8)&0xff, (*ip>>16)&0xff, (*ip>>24)&0xff);
if (nat_entry>=NAT_TAB_SIZE) goto recv_abrt;
if (*ip!=nattab[nat_entry].src_ip || port != nattab[nat_entry].src_port || nattab[nat_entry].proto != PROT_TCP) {nattab[nat_entry].errors++; goto recv_abrt; }
uint16_t idx=nattab[nat_entry].index_end;
if (idx>=SNDQ_MAXLEN) { nattab[nat_entry].errors++; goto recv_abrt; }
int idx_next=idx+1;
if (idx_next>=SNDQ_MAXLEN) idx_next=0;
if (idx_next==nattab[nat_entry].index_begin) { nattab[nat_entry].rx_ovf++; print_log("[NAT_LWTCP_RECV] RX_OVF: idx_b=%d idx_e=%d", nattab[nat_entry].index_begin, nattab[nat_entry].index_end ); goto recv_abrt; }
// print_log("[NAT_TCP] tab %d LWIP RECV %d/%d bytes", nat_entry, p->len, p->tot_len);
if (nattab[nat_entry].pcb!=pcb) { print_log("[NAT_TCP] PCB not match!!!!!!!!!!!!!!!!"); while(1);}
nattab[nat_entry].p[idx]=p;
nattab[nat_entry].index_end=idx_next;
nat_stat.pbuf_used++;
// TNotifyAdd( &tNotifyHandle, taskNOTIFY_NEW_DATA);
write(nat_task_pipe[1], "1",1);// notify for new data
// nattab[nat_entry].shutdown_req=1;
// nat_close_so_conn(nat_entry);
// nat_close_lw_conn(nat_entry);
return ERR_OK;
recv_abrt:
if (p) {
tcp_recved(pcb, p->tot_len);
pbuf_free(p);
}
return ERR_OK;
// return ERR_ABRT;
}
static err_t nat_accept_fn(void *arg, struct tcp_pcb *pcb, err_t err) {
// print_log("[NAT_TCP] === NEW connection callback");
if ((err != ERR_OK) || (pcb == NULL)) { return ERR_VAL; }
uint8_t* ip=(uint8_t*)&pcb->remote_ip.addr;
uint16_t port=pcb->remote_port;
print_log("[NAT_TCP] === NEW connecion from %d.%d.%d.%d:%d", ip[0],ip[1],ip[2],ip[3], port);
int entry=nat_find_match(pcb->remote_ip.addr, htons(pcb->remote_port), PROT_TCP);
if (entry<0) return ERR_VAL;
tcp_arg(pcb, (void*)(entry+1));// arg for this TCP connection
int s=socket(AF_INET, SOCK_STREAM, 0);
if (s==-1) { print_log("[NAT_TCP] tab %d socket allocation err", entry); return ERR_VAL; }
int status = fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK);
if (status==-1) { close(s); print_log("[NAT_TCP] tab %d FCNTL error", entry); return ERR_VAL; }
int keepcnt = 8;
int keepidle = 2;
int keepintvl = 2;
int nodelay = 1;
int syncnt = 3;
setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(int));
setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(int));
setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(int));
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(int));
setsockopt(s, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(int));
tcp_nagle_disabled(pcb);
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = nattab[entry].dst_ip;
servaddr.sin_port = nattab[entry].dst_port;
ip=(uint8_t*)&servaddr.sin_addr.s_addr;
port=htons(servaddr.sin_port);
print_log("[NAT_TCP] === connecion to %d.%d.%d.%d:%d", ip[0],ip[1],ip[2],ip[3], port);
int r=connect(s, (struct sockaddr*)&servaddr, sizeof(servaddr));
if (r != 0) if (errno != EINPROGRESS)
{
print_log("[NAT_TCP] tab %d can not connect: %d", entry, errno);
close(s);
return ERR_VAL;
}
nattab[entry].socket=s;
nattab[entry].status=1;
nattab[entry].index_begin=0;
nattab[entry].index_end=0;
nattab[entry].offs=0;
nattab[entry].shutdown_req=0;
nattab[entry].pcb=pcb;
print_log("[NAT_TCP] tab %d new remote TCP conn", entry);
/* Set up the various callback functions */
tcp_recv(pcb, nat_tcp_recv);
tcp_err(pcb, nat_tcp_err);
// tcp_poll(pcb, nat_tcp_poll, HTTPD_POLL_INTERVAL);
tcp_sent(pcb, nat_tcp_sent);
nat_stat.tcp_new++;
write(nat_task_pipe[1], "1",1);// notify for new connection
write(nat_rx_task_pipe[1], "1",1);// notify for new connection
return ERR_OK;
}
void eth_nat_init() {
int ret=pipe2(&nat_task_pipe, O_NONBLOCK);
ret=pipe2(&nat_rx_task_pipe, O_NONBLOCK);
if (ret) return;
fcntl(nat_task_pipe[0], F_SETFL, O_NONBLOCK);
fcntl(nat_rx_task_pipe[0], F_SETFL, O_NONBLOCK);
fcntl(nat_task_pipe[1], F_SETFL, O_NONBLOCK);
fcntl(nat_rx_task_pipe[1], F_SETFL, O_NONBLOCK);
// TNotifyCreate(&tNotifyHandle);
TaskCreate (NAT_Task, &tnatHandle);
TaskCreate (NAT_RX_Task, &tnatRXHandle);
pthread_t tstats;
TaskCreate (calc_stats, &tstats);
nat_tcp=tcp_new_ip_type(IPADDR_TYPE_V4);
if (nat_tcp==NULL) return;
tcp_bind(nat_tcp, IP_ANY_TYPE, NAT_DIVERT_PORT);
err_t err;
nat_tcp=tcp_listen_with_backlog_and_err(nat_tcp, 10, &err);
if (nat_tcp==NULL) { print_log("[NAT_TCP] === NAT tcp listen failed (err %d)", err); return; }
tcp_accept(nat_tcp, nat_accept_fn);
// print_log("[NAT_TCP] === NAT INIT");
}
+40
View File
@@ -0,0 +1,40 @@
#define NAT_TAB_SIZE 16
#define SNDQ_MAXLEN 100
struct NAT_TAB {
uint32_t src_ip;// порядок байт в сетевом формате
uint32_t dst_ip;// порядок байт в сетевом формате
uint16_t src_port;// порядок байт в сетевом формате
uint16_t dst_port;// порядок байт в сетевом формате
uint16_t proto;
uint32_t time;
struct pbuf* p[SNDQ_MAXLEN];// очередь приема с lwip
uint8_t txbuf[1500];// на передачу в lwip
uint16_t txbuf_len;
struct tcp_pcb *pcb;// null - free
uint32_t index_begin;
uint32_t index_end;
uint32_t status;// 0-free, 1-active (for TCP-based entries)
int socket;
uint32_t offs;
uint32_t errors;
uint32_t rx_ovf;
uint32_t shutdown_req;// 1 - waiting for shutdown sockets
};
struct NAT_STAT {
uint32_t pbuf_broken;
uint32_t tcp_new;
uint32_t tcp_close;
uint32_t pbuf_used;
uint32_t lw_conn_used;
uint32_t so_conn_used;
};
extern struct NAT_STAT nat_stat;
int forward_nat(struct ETH_QUEUE* block);
int backward_nat(struct ETH_QUEUE* block);
void eth_nat_init();
+34
View File
@@ -0,0 +1,34 @@
#include "eth_mem.h"
#include "eth_queue.h"
void add_to_custom_queue(struct pbuf* p, struct ETH_Q* q) {
p->next = NULL;
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
if (q->q_len>=q->q_len_max) {// очередь уже полна. дропаем пакет.
q->lost++;
ETH_MEM_UNPROTECT();
pbuf_free(p);
return;
}
if (q->q_end) q->q_end->next=p; else q->q_begin=p;// этот элемент приписываем к концу очереди
q->q_end=p;// конечным элементом ставим этот элемент
q->q_len++;
if (q->q_len_max<q->q_len) q->q_len_max=q->q_len;
ETH_MEM_UNPROTECT();
}
struct pbuf* get_from_custom_queue(struct ETH_Q* q) {
ETH_MEM_DECL_PROTECT();
ETH_MEM_PROTECT();
struct pbuf* p=(struct pbuf*)q->q_begin;
if (p==NULL) { ETH_MEM_UNPROTECT(); return NULL; }
struct pbuf* next_pbuf=p->next;
q->q_begin=next_pbuf;
if (next_pbuf == NULL) q->q_end = NULL;
if (q->q_len==0) EM_ASSERT(7);// ASSERT: сбой подсчета размера очереди.
q->q_len--;
ETH_MEM_UNPROTECT();
p->next=NULL;
return p;
}
+14
View File
@@ -0,0 +1,14 @@
struct ETH_Q {
struct pbuf* q_begin;
struct pbuf* q_end;
uint32_t q_len;
uint32_t q_len_max;
uint32_t lost;
};
// добавить ETH_PBUF p в очередь q
void add_to_custom_queue(struct pbuf* p, struct ETH_Q* q);
// возврат - NULL - очередь пуста; иначе pbuf
struct pbuf* get_from_custom_queue(struct ETH_Q* q);
+124
View File
@@ -0,0 +1,124 @@
#include <stdint.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include "eth_mem.h"
#include "eth_router.h"
#include "eth_router_cfg.h"
#include "eth_nat.h"
struct ETH_ROUTER_STATS eth_router_stats;
struct ETH_QUEUEPOOL_CTRL xeth_queuepool_ctrl;
struct ETH_QUEUE xeth_queuepool[ETH_MEM_BUFS_CNT] ETH_MEM_ALIGN;
struct ETH_PBUF_CTRL xeth_pbuf_ctrl;
struct ETH_PBUF eth_pbuf[ETH_PBUFS_CNT];
uint8_t eth_pbuf_mem[ETH_PBUFS_CNT*ETH_MEM_BUF_SIZE];// граница элементов кратна 32 байтам. иначе будут проблемки с кешем.
struct ETH_NETIF eth_netif_array[ETH_NETIFS];
void eth_router_init() {
eth_router_add_bridge(&xeth_queuepool_ctrl, xeth_queuepool, ETH_MEM_BUFS_CNT, &xeth_pbuf_ctrl, eth_pbuf, eth_pbuf_mem, ETH_PBUFS_CNT, eth_netif_array, ETH_NETIFS);
eth_router_start_task(&xeth_queuepool_ctrl);
}
#define ETHTYPE_IPV4 0x0800
#define ETHTYPE_IPV6 0x86DD
#define ETHTYPE_ARP 0x0806
#define ETHTYPE_ADP 0x8777// braodcast топологии
#define ETHTYPE_DBG 0x8778// unicast diagram
#define ETHTYPE_CONTROLS 0x8779// controls, terminal, gui controls
void sprint_pkt(char* pkt, int pkt_len) {
char textbuf[1000];
char textptr=0;
textptr+=sprintf(textbuf+textptr,"DMAC=%02X:%02X:%02X:%02X:%02X:%02X ",pkt[0],pkt[1],pkt[2],pkt[3],pkt[4],pkt[5]);
textptr+=sprintf(textbuf+textptr,"SMAC=%02X:%02X:%02X:%02X:%02X:%02X ",pkt[6],pkt[7],pkt[8],pkt[9],pkt[10],pkt[11]);
uint16_t ethertype=(pkt[12]<<8)+pkt[13];
textptr+=sprintf(textbuf+textptr,"ET=%04X ",ethertype);
if (ethertype == ETHTYPE_ARP) {
textptr+=sprintf(textbuf+textptr,"[ARP] ");
}
if (ethertype == ETHTYPE_IPV4) {
textptr+=sprintf(textbuf+textptr,"[IP4] ");
}
if (ethertype == ETHTYPE_ADP) {
textptr+=sprintf(textbuf+textptr,"[ADP] ");
}
if (ethertype == ETHTYPE_DBG) {
textptr+=sprintf(textbuf+textptr,"[DBG] ");
}
if (ethertype == ETHTYPE_CONTROLS) {
textptr+=sprintf(textbuf+textptr,"[CTR] ");
}
if (ethertype == ETHTYPE_ADP || ethertype == ETHTYPE_DBG || ethertype == ETHTYPE_CONTROLS) {
}
textptr+=sprintf(textbuf+textptr,"LEN=%d ",pkt_len);
print_log("%s",textbuf);
}
int prev_num;
void eth_route_block(struct ETH_QUEUE* block) {
if (block->pbuf->pbuf.ref==0) EM_ASSERT(20);
int pbuf_num=(block->pbuf-eth_pbuf);
uint32_t src_netif=block->pbuf->pbuf.if_idx;
// sprint_pkt(block->pbuf->pbuf.payload, block->pbuf->pbuf.len);
/*if (src_netif == LWIP_NETIF_ID) {
print_log("Route pbuf from lwip");
sprint_pkt(block->pbuf->pbuf.payload, block->pbuf->pbuf.len);
}*/
if (src_netif>=ETH_NETIFS) EM_ASSERT(21);// assert: invalid netif
if (src_netif==0) EM_ASSERT(22);// assert: invalid netif
if (src_netif==TEST_NETIF_ID) eth_router_stats.in_test++;
if (src_netif==BLE_NETIF_ID) eth_router_stats.in_ble++;
if (eth_netif_array[src_netif].if_up==0) {// src interface is down: drop packet & exit
block->pool->eth_netif_array[src_netif].dgrams_lost++;
eth_pbuf_free_request(block->pbuf);
eth_queue_entry_free(block);
print_log("interface (%d) is not up, dropping dgram ",src_netif);
return;
}
// block->pool->eth_netif_array[src_netif].dgrams_lost++;
uint32_t dst_netif=src_netif;
if (src_netif == BLE_NETIF_ID) {
forward_nat(block);
dst_netif=LWIP_NETIF_ID;
}
if (src_netif == LWIP_NETIF_ID) {
backward_nat(block);
dst_netif=BLE_NETIF_ID;
}
if (dst_netif>=ETH_NETIFS) EM_ASSERT(23);// assert: invalid netif
if (dst_netif==0) {
eth_pbuf_free_request(block->pbuf);
eth_queue_entry_free(block);
return;
}
eth_add_packet_to_output_queue(block, &block->pool->eth_netif_array[dst_netif]);
}
+58
View File
@@ -0,0 +1,58 @@
#pragma once
#include "eth_mem.h"
struct __attribute__((__packed__)) MAC_ADDR {
uint32_t mac32;
uint16_t mac16;
};
struct __attribute__((__packed__)) ETH_PKT_HDR {
struct MAC_ADDR dst_mac;
struct MAC_ADDR src_mac;
uint16_t ethertype;
uint8_t tos_hdrl;
uint8_t dscp;
uint16_t len;
uint16_t id;
uint16_t frag_offs;
uint8_t ttl;
uint8_t proto;
uint16_t hdr_csum;
uint32_t ip_src;
uint32_t ip_dst;
uint16_t port_src;// tcp/udp hdr
uint16_t port_dst;
};
struct MAC_LOOKUP_TAB {
struct MAC_ADDR mac;
uint16_t time_upd;
uint8_t if_idx;
};
struct ETH_ROUTER_STATS {
uint32_t in_test;
uint32_t in_ble;
uint32_t out_if_not_found;
uint32_t test_err;
};
extern struct ETH_ROUTER_STATS eth_router_stats;
void eth_route_block(struct ETH_QUEUE* block);
uint32_t mac_search(struct MAC_ADDR mac);
// проинициализировать мост по умолчанию (запускает eth_router_add_bridge с дефолтным пулом)
void eth_router_init();
void notify_eth_ble_send_queue_update();
void notify_eth_uart_send_queue_update();
//extern struct ETH_QUEUE xeth_queuepool[ETH_MEM_BUFS_CNT];
extern struct ETH_QUEUEPOOL_CTRL xeth_queuepool_ctrl;
extern struct ETH_QUEUE xeth_queuepool[ETH_MEM_BUFS_CNT];
extern struct ETH_PBUF_CTRL xeth_pbuf_ctrl;
extern struct ETH_PBUF eth_pbuf[ETH_PBUFS_CNT];
extern uint8_t eth_pbuf_mem[ETH_PBUFS_CNT*ETH_MEM_BUF_SIZE];
extern struct ETH_NETIF eth_netif_array[ETH_NETIFS];
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#define ETH_MEM_BUFS_CNT 100 // количество буферов (занимают ETH_MEM_BUF_SIZE байт)
#define ETH_PBUFS_CNT 400// (занимают один pbuf)
#define ETH_MEM_BUF_SIZE 1600// размер данных ethernet пакета (начиная с мак адресов)
#define ETH_NETIFS 4// макс. количество интерфейсов
// номер интерфейса в роутере (начиная с единицы)
#define LWIP_NETIF_ID 1
#define TEST_NETIF_ID 2
#define BLE_NETIF_ID 3
// Зармеры исходящих очередей на интерфейсы
#define LWIP_NETIF_QLEN 20
#define UART_NETIF_QLEN 20
#define BLE_NETIF_QLEN 20
#define IN_BLE_NETIF_QLEN_THR 3
#define IN_UART_NETIF_QLEN_THR 3
+138
View File
@@ -0,0 +1,138 @@
#include "stdint.h"
uint8_t imageCubes[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xe3, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xf1, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x60, 0xff, 0xff, 0xff, 0xff, 0x00, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0xe0, 0xff, 0xff, 0xff, 0xf0, 0xfe, 0x00, 0xe0, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf1, 0xe0, 0x7f, 0xff, 0xff, 0xf0, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe1, 0xc0, 0x7f, 0xff, 0xff, 0xf2, 0x7e, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe1, 0xd8, 0x7f, 0xff, 0xff, 0xf1, 0x30, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc1, 0xb8, 0x3f, 0xff, 0xff, 0xf0, 0xf8, 0x00, 0x07, 0xc7, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x78, 0x3f, 0xff, 0xff, 0xf0, 0x7c, 0x00, 0x0f, 0xe3, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x70, 0x1f, 0xff, 0xff, 0xfc, 0x7e, 0x00, 0x0f, 0xe1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0xf0, 0x1f, 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0x03, 0xc1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0xee, 0x1f, 0xff, 0xff, 0xfe, 0x1f, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x00, 0x5e, 0x1f, 0xff, 0xff, 0xfe, 0x1f, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf9, 0x80, 0x1e, 0x3f, 0xff, 0xff, 0xfe, 0x0f, 0xf0, 0x1f, 0xe0, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xf3, 0x80, 0x3c, 0x3f, 0xff, 0xff, 0xfe, 0x07, 0xe3, 0xfc, 0x00, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xe7, 0x80, 0x3c, 0x7d, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xe7, 0x80, 0x38, 0xe0, 0x7f, 0xcf, 0xfd, 0x63, 0xf8, 0x00, 0x38, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xc7, 0x00, 0x10, 0xc1, 0x1f, 0xe7, 0xff, 0x77, 0xf0, 0x00, 0x7c, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xc6, 0xc0, 0x01, 0x00, 0x4e, 0x73, 0xff, 0x77, 0xf0, 0x00, 0xfc, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xc1, 0xe0, 0x02, 0x0e, 0x33, 0x3b, 0xff, 0x77, 0xee, 0x00, 0xf8, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xc1, 0xc0, 0x06, 0x1f, 0x7d, 0x9d, 0xff, 0x73, 0xff, 0x01, 0xf8, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe3, 0xc0, 0x0c, 0x3f, 0xbe, 0x45, 0xff, 0xfb, 0xff, 0x00, 0xf0, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe3, 0x80, 0x18, 0x7f, 0xbf, 0x90, 0xff, 0xf3, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe3, 0xb0, 0x30, 0x7f, 0xbf, 0xe8, 0xff, 0xf3, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x70, 0x60, 0x7f, 0x3f, 0xf2, 0x7f, 0xf3, 0xfe, 0x18, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0xf0, 0x40, 0x3e, 0x1f, 0xfd, 0xff, 0xf3, 0xd8, 0x7c, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0xf0, 0x80, 0x00, 0x0f, 0xfe, 0x7f, 0xf3, 0xe0, 0xfc, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf1, 0xe1, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf3, 0xf8, 0xfc, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf1, 0xc2, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf3, 0xf8, 0xfc, 0x01, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x84, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf3, 0xfe, 0xf8, 0xf1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x08, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf3, 0xff, 0x21, 0xf1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x10, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf3, 0xff, 0xc3, 0xf1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x30, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf3, 0xff, 0xf3, 0xf3, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x60, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x80, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xbf, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xdf, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xdf, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x3f, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x0c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
uint8_t imageWolf[] = {
0xff, 0xff, 0xff, 0x8f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf3, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xf9, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x7f, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf9, 0x80, 0x7f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf9, 0xea, 0x9f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0xd5, 0x7f, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfb, 0x29, 0x54, 0x5f, 0x9f, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xb1, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfa, 0x80, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x5f, 0xc0, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x07, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xe0, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xb0, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa8, 0x60, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xfd, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x37, 0x20, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x01, 0xe0, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0xe0, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0xd0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3e, 0xe0, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x7f, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xfd, 0xf0, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0x0c, 0x7f, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc4, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x0f, 0x1f, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf7, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x7f, 0xfa, 0xff, 0xef, 0xff, 0xff, 0xff, 0x28, 0x0b, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfd, 0xff, 0xdf, 0xff, 0xf7, 0xff, 0xff, 0xfe, 0xc0, 0x2b, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xfe, 0xff, 0xff, 0xfd, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x97, 0xff, 0xfb, 0xff, 0xff, 0xed, 0x4a, 0x95, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xd2, 0xbf, 0xfa, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xd3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xd7, 0xff, 0xfd, 0x3f, 0xff, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf4, 0x9f, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x9d, 0x9f, 0xff, 0x67, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xff, 0x4c, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xbf, 0xff, 0xc9, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xb8, 0x7f, 0xff, 0xc3, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xfc, 0x7f, 0xff, 0x86, 0x31, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xfe, 0x3f, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0x3f, 0xff, 0x3f, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfe, 0xbf, 0xff, 0x3f, 0x3f, 0xd7, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0x7f, 0xfa, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xff, 0xff, 0xef, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xfe, 0x0f, 0xff,
0xff, 0xff, 0xff, 0xef, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xa9, 0x17, 0xef, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xee, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf1, 0xbf, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xfc, 0x4f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7e, 0x17, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8b, 0xc7, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xb3, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x93, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xf7, 0x47, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xfb, 0xa3, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xfe, 0xd3, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x9f, 0xbf,
0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xfe, 0x1e, 0xef, 0xbf, 0xe7, 0xf7, 0xee, 0xdf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0x80, 0x80, 0xff, 0x27, 0xff, 0xfd, 0xff, 0xe2, 0x6f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xf8, 0x0f, 0xcf, 0xd7, 0xff, 0xff, 0xff, 0xf1, 0x37,
0xff, 0xff, 0xff, 0xfe, 0xc7, 0xf9, 0x9f, 0xff, 0xbf, 0x9b, 0xf7, 0xff, 0xfb, 0xff, 0xf8, 0x13,
0xff, 0xff, 0xff, 0xff, 0xdf, 0xe8, 0xcb, 0xfe, 0x1e, 0x1b, 0xbd, 0xff, 0xff, 0xff, 0xf4, 0x1b,
0xff, 0xff, 0xff, 0xff, 0x1f, 0xdc, 0xe3, 0xfd, 0x8f, 0x1d, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x83,
0xff, 0xff, 0xff, 0xff, 0x1f, 0xdc, 0xe3, 0xfd, 0x8f, 0x1d, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x83,
0xff, 0xff, 0xff, 0xff, 0x1f, 0xdc, 0xe3, 0xfd, 0x8f, 0x1d, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x83,
};
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+115
View File
@@ -0,0 +1,115 @@
/**
* @file
* Error Management module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/err.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/errno.h"
#if !NO_SYS
/** Table to quickly map an lwIP error (err_t) to a socket error
* by using -err as an index */
static const int err_to_errno_table[] = {
0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
EINVAL, /* ERR_VAL -6 Illegal value. */
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
EADDRINUSE, /* ERR_USE -8 Address in use. */
EALREADY, /* ERR_ALREADY -9 Already connecting. */
EISCONN, /* ERR_ISCONN -10 Conn already established.*/
ENOTCONN, /* ERR_CONN -11 Not connected. */
-1, /* ERR_IF -12 Low-level netif error */
ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */
ECONNRESET, /* ERR_RST -14 Connection reset. */
ENOTCONN, /* ERR_CLSD -15 Connection closed. */
EIO /* ERR_ARG -16 Illegal argument. */
};
int
err_to_errno(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) {
return EIO;
}
return err_to_errno_table[-err];
}
#endif /* !NO_SYS */
#ifdef LWIP_DEBUG
static const char *err_strerr[] = {
"Ok.", /* ERR_OK 0 */
"Out of memory error.", /* ERR_MEM -1 */
"Buffer error.", /* ERR_BUF -2 */
"Timeout.", /* ERR_TIMEOUT -3 */
"Routing problem.", /* ERR_RTE -4 */
"Operation in progress.", /* ERR_INPROGRESS -5 */
"Illegal value.", /* ERR_VAL -6 */
"Operation would block.", /* ERR_WOULDBLOCK -7 */
"Address in use.", /* ERR_USE -8 */
"Already connecting.", /* ERR_ALREADY -9 */
"Already connected.", /* ERR_ISCONN -10 */
"Not connected.", /* ERR_CONN -11 */
"Low-level netif error.", /* ERR_IF -12 */
"Connection aborted.", /* ERR_ABRT -13 */
"Connection reset.", /* ERR_RST -14 */
"Connection closed.", /* ERR_CLSD -15 */
"Illegal argument." /* ERR_ARG -16 */
};
/**
* Convert an lwip internal error to a string representation.
*
* @param err an lwip internal err_t
* @return a string representation for err
*/
const char *
lwip_strerr(err_t err)
{
if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) {
return "Unknown error.";
}
return err_strerr[-err];
}
#endif /* LWIP_DEBUG */
+102
View File
@@ -0,0 +1,102 @@
/**
* @file
* Interface Identification APIs from:
* RFC 3493: Basic Socket Interface Extensions for IPv6
* Section 4: Interface Identification
*
* @defgroup if_api Interface Identification API
* @ingroup socket
*/
/*
* Copyright (c) 2017 Joel Cunningham, Garmin International, Inc. <joel.cunningham@garmin.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Joel Cunningham <joel.cunningham@me.com>
*
*/
#include "lwip/opt.h"
#if LWIP_SOCKET
#include "lwip/errno.h"
#include "lwip/if_api.h"
#include "lwip/netifapi.h"
#include "lwip/priv/sockets_priv.h"
/**
* @ingroup if_api
* Maps an interface index to its corresponding name.
* @param ifindex interface index
* @param ifname shall point to a buffer of at least {IF_NAMESIZE} bytes
* @return If ifindex is an interface index, then the function shall return the
* value supplied in ifname, which points to a buffer now containing the interface name.
* Otherwise, the function shall return a NULL pointer.
*/
char *
lwip_if_indextoname(unsigned int ifindex, char *ifname)
{
#if LWIP_NETIF_API
if (ifindex <= 0xff) {
err_t err = netifapi_netif_index_to_name((u8_t)ifindex, ifname);
if (!err && ifname[0] != '\0') {
return ifname;
}
}
#else /* LWIP_NETIF_API */
LWIP_UNUSED_ARG(ifindex);
LWIP_UNUSED_ARG(ifname);
#endif /* LWIP_NETIF_API */
set_errno(ENXIO);
return NULL;
}
/**
* @ingroup if_api
* Returs the interface index corresponding to name ifname.
* @param ifname Interface name
* @return The corresponding index if ifname is the name of an interface;
* otherwise, zero.
*/
unsigned int
lwip_if_nametoindex(const char *ifname)
{
#if LWIP_NETIF_API
err_t err;
u8_t idx;
err = netifapi_netif_name_to_index(ifname, &idx);
if (!err) {
return idx;
}
#else /* LWIP_NETIF_API */
LWIP_UNUSED_ARG(ifname);
#endif /* LWIP_NETIF_API */
return 0; /* invalid index */
}
#endif /* LWIP_SOCKET */
+669
View File
@@ -0,0 +1,669 @@
/**
* @file
* Sequential API Main thread module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
#include "lwip/priv/tcpip_priv.h"
#include "lwip/sys.h"
#include "lwip/memp.h"
#include "lwip/mem.h"
#include "lwip/init.h"
#include "lwip/ip.h"
#include "lwip/pbuf.h"
#include "lwip/etharp.h"
#include "netif/ethernet.h"
#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
/* global variables */
static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg;
static sys_mbox_t tcpip_mbox;
#if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */
sys_mutex_t lock_tcpip_core;
#endif /* LWIP_TCPIP_CORE_LOCKING */
static void tcpip_thread_handle_msg(struct tcpip_msg *msg);
#if !LWIP_TIMERS
/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
#else /* !LWIP_TIMERS */
/* wait for a message, timeouts are processed while waiting */
#define TCPIP_MBOX_FETCH(mbox, msg) tcpip_timeouts_mbox_fetch(mbox, msg)
/**
* Wait (forever) for a message to arrive in an mbox.
* While waiting, timeouts are processed.
*
* @param mbox the mbox to fetch the message from
* @param msg the place to store the message
*/
static void
tcpip_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
{
u32_t sleeptime, res;
again:
LWIP_ASSERT_CORE_LOCKED();
sleeptime = sys_timeouts_sleeptime();
if (sleeptime == SYS_TIMEOUTS_SLEEPTIME_INFINITE) {
UNLOCK_TCPIP_CORE();
sys_arch_mbox_fetch(mbox, msg, 0);
LOCK_TCPIP_CORE();
return;
} else if (sleeptime == 0) {
sys_check_timeouts();
/* We try again to fetch a message from the mbox. */
goto again;
}
UNLOCK_TCPIP_CORE();
res = sys_arch_mbox_fetch(mbox, msg, sleeptime);
LOCK_TCPIP_CORE();
if (res == SYS_ARCH_TIMEOUT) {
/* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred
before a message could be fetched. */
sys_check_timeouts();
/* We try again to fetch a message from the mbox. */
goto again;
}
}
#endif /* !LWIP_TIMERS */
/**
* The main lwIP thread. This thread has exclusive access to lwIP core functions
* (unless access to them is not locked). Other threads communicate with this
* thread using message boxes.
*
* It also starts all the timers to make sure they are running in the right
* thread context.
*
* @param arg unused argument
*/
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
SemaphoreHandle_t ipSemaphore = NULL;
static void
tcpip_thread(void *arg)
{
struct tcpip_msg *msg;
LWIP_UNUSED_ARG(arg);
ipSemaphore = xSemaphoreCreateMutex();
xSemaphoreGive( ipSemaphore );
LWIP_MARK_TCPIP_THREAD();
LOCK_TCPIP_CORE();
if (tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);
}
while (1) { /* MAIN Loop */
LWIP_TCPIP_THREAD_ALIVE();
/* wait for a message, timeouts are processed while waiting */
TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg);
if (msg == NULL) {
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
LWIP_ASSERT("tcpip_thread: invalid message", 0);
continue;
}
if( xSemaphoreTake( ipSemaphore, ( TickType_t ) 0 ) ) {
tcpip_thread_handle_msg(msg);
xSemaphoreGive( ipSemaphore );
}
}
}
/* Handle a single tcpip_msg
* This is in its own function for access by tests only.
*/
static void
tcpip_thread_handle_msg(struct tcpip_msg *msg)
{
switch (msg->type) {
#if !LWIP_TCPIP_CORE_LOCKING
case TCPIP_MSG_API:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
msg->msg.api_msg.function(msg->msg.api_msg.msg);
break;
case TCPIP_MSG_API_CALL:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
sys_sem_signal(msg->msg.api_call.sem);
break;
#endif /* !LWIP_TCPIP_CORE_LOCKING */
#if !LWIP_TCPIP_CORE_LOCKING_INPUT
case TCPIP_MSG_INPKT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
if (msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif) != ERR_OK) {
pbuf_free(msg->msg.inp.p);
}
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
break;
#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
case TCPIP_MSG_TIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
case TCPIP_MSG_UNTIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
case TCPIP_MSG_CALLBACK:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
msg->msg.cb.function(msg->msg.cb.ctx);
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
case TCPIP_MSG_CALLBACK_STATIC:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
msg->msg.cb.function(msg->msg.cb.ctx);
break;
default:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
LWIP_ASSERT("tcpip_thread: invalid message", 0);
break;
}
}
#ifdef TCPIP_THREAD_TEST
/** Work on queued items in single-threaded test mode */
int
tcpip_thread_poll_one(void)
{
int ret = 0;
struct tcpip_msg *msg;
if (sys_arch_mbox_tryfetch(&tcpip_mbox, (void **)&msg) != SYS_ARCH_TIMEOUT) {
LOCK_TCPIP_CORE();
if (msg != NULL) {
tcpip_thread_handle_msg(msg);
ret = 1;
}
UNLOCK_TCPIP_CORE();
}
return ret;
}
#endif
/**
* Pass a received packet to tcpip_thread for input processing
*
* @param p the received packet
* @param inp the network interface on which the packet was received
* @param input_fn input function to call
*/
err_t
tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
{
#if LWIP_TCPIP_CORE_LOCKING_INPUT
err_t ret;
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
LOCK_TCPIP_CORE();
ret = input_fn(p, inp);
UNLOCK_TCPIP_CORE();
return ret;
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_INPKT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
msg->msg.inp.input_fn = input_fn;
if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
return ERR_MEM;
}
return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
}
/**
* @ingroup lwip_os
* Pass a received packet to tcpip_thread for input processing with
* ethernet_input or ip_input. Don't call directly, pass to netif_add()
* and call netif->input().
*
* @param p the received packet, p->payload pointing to the Ethernet header or
* to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
* NETIF_FLAG_ETHERNET flags)
* @param inp the network interface on which the packet was received
*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
#if LWIP_ETHERNET
if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
return tcpip_inpkt(p, inp, ethernet_input);
} else
#endif /* LWIP_ETHERNET */
return tcpip_inpkt(p, inp, ip_input);
}
/**
* @ingroup lwip_os
* Call a specific function in the thread context of
* tcpip_thread for easy access synchronization.
* A function called in that way may access lwIP core code
* without fearing concurrent access.
* Blocks until the request is posted.
* Must not be called from interrupt context!
*
* @param function the function to call
* @param ctx parameter passed to f
* @return ERR_OK if the function was called, another err_t if not
*
* @see tcpip_try_callback
*/
err_t
tcpip_callback(tcpip_callback_fn function, void *ctx)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_CALLBACK;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
sys_mbox_post(&tcpip_mbox, msg);
return ERR_OK;
}
/**
* @ingroup lwip_os
* Call a specific function in the thread context of
* tcpip_thread for easy access synchronization.
* A function called in that way may access lwIP core code
* without fearing concurrent access.
* Does NOT block when the request cannot be posted because the
* tcpip_mbox is full, but returns ERR_MEM instead.
* Can be called from interrupt context.
*
* @param function the function to call
* @param ctx parameter passed to f
* @return ERR_OK if the function was called, another err_t if not
*
* @see tcpip_callback
*/
err_t
tcpip_try_callback(tcpip_callback_fn function, void *ctx)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_CALLBACK;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_API, msg);
return ERR_MEM;
}
return ERR_OK;
}
#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
/**
* call sys_timeout in tcpip_thread
*
* @param msecs time in milliseconds for timeout
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
err_t
tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_TIMEOUT;
msg->msg.tmo.msecs = msecs;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
sys_mbox_post(&tcpip_mbox, msg);
return ERR_OK;
}
/**
* call sys_untimeout in tcpip_thread
*
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
err_t
tcpip_untimeout(sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_UNTIMEOUT;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
sys_mbox_post(&tcpip_mbox, msg);
return ERR_OK;
}
#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
/**
* Sends a message to TCPIP thread to call a function. Caller thread blocks on
* on a provided semaphore, which ist NOT automatically signalled by TCPIP thread,
* this has to be done by the user.
* It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way
* with least runtime overhead.
*
* @param fn function to be called from TCPIP thread
* @param apimsg argument to API function
* @param sem semaphore to wait on
* @return ERR_OK if the function was called, another err_t if not
*/
err_t
tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
{
#if LWIP_TCPIP_CORE_LOCKING
LWIP_UNUSED_ARG(sem);
LOCK_TCPIP_CORE();
fn(apimsg);
UNLOCK_TCPIP_CORE();
return ERR_OK;
#else /* LWIP_TCPIP_CORE_LOCKING */
TCPIP_MSG_VAR_DECLARE(msg);
LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
TCPIP_MSG_VAR_ALLOC(msg);
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
sys_mbox_post(&tcpip_mbox, &TCPIP_MSG_VAR_REF(msg));
sys_arch_sem_wait(sem, 0);
TCPIP_MSG_VAR_FREE(msg);
return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
/**
* Synchronously calls function in TCPIP thread and waits for its completion.
* It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or
* LWIP_NETCONN_SEM_PER_THREAD.
* If not, a semaphore is created and destroyed on every call which is usually
* an expensive/slow operation.
* @param fn Function to call
* @param call Call parameters
* @return Return value from tcpip_api_call_fn
*/
err_t
tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
{
#if LWIP_TCPIP_CORE_LOCKING
err_t err;
LOCK_TCPIP_CORE();
err = fn(call);
UNLOCK_TCPIP_CORE();
return err;
#else /* LWIP_TCPIP_CORE_LOCKING */
TCPIP_MSG_VAR_DECLARE(msg);
#if !LWIP_NETCONN_SEM_PER_THREAD
err_t err = sys_sem_new(&call->sem, 0);
if (err != ERR_OK) {
return err;
}
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
TCPIP_MSG_VAR_ALLOC(msg);
TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
#if LWIP_NETCONN_SEM_PER_THREAD
TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
#else /* LWIP_NETCONN_SEM_PER_THREAD */
TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
sys_mbox_post(&tcpip_mbox, &TCPIP_MSG_VAR_REF(msg));
sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
TCPIP_MSG_VAR_FREE(msg);
#if !LWIP_NETCONN_SEM_PER_THREAD
sys_sem_free(&call->sem);
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
return call->err;
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
/**
* @ingroup lwip_os
* Allocate a structure for a static callback message and initialize it.
* The message has a special type such that lwIP never frees it.
* This is intended to be used to send "static" messages from interrupt context,
* e.g. the message is allocated once and posted several times from an IRQ
* using tcpip_callbackmsg_trycallback().
* Example usage: Trigger execution of an ethernet IRQ DPC routine in lwIP thread context.
*
* @param function the function to call
* @param ctx parameter passed to function
* @return a struct pointer to pass to tcpip_callbackmsg_trycallback().
*
* @see tcpip_callbackmsg_trycallback()
* @see tcpip_callbackmsg_delete()
*/
struct tcpip_callback_msg *
tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
{
struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) {
return NULL;
}
msg->type = TCPIP_MSG_CALLBACK_STATIC;
msg->msg.cb.function = function;
msg->msg.cb.ctx = ctx;
return (struct tcpip_callback_msg *)msg;
}
/**
* @ingroup lwip_os
* Free a callback message allocated by tcpip_callbackmsg_new().
*
* @param msg the message to free
*
* @see tcpip_callbackmsg_new()
*/
void
tcpip_callbackmsg_delete(struct tcpip_callback_msg *msg)
{
memp_free(MEMP_TCPIP_MSG_API, msg);
}
/**
* @ingroup lwip_os
* Try to post a callback-message to the tcpip_thread tcpip_mbox.
*
* @param msg pointer to the message to post
* @return sys_mbox_trypost() return code
*
* @see tcpip_callbackmsg_new()
*/
err_t
tcpip_callbackmsg_trycallback(struct tcpip_callback_msg *msg)
{
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
return sys_mbox_trypost(&tcpip_mbox, msg);
}
/**
* @ingroup lwip_os
* Try to post a callback-message to the tcpip_thread mbox.
* Same as @ref tcpip_callbackmsg_trycallback but calls sys_mbox_trypost_fromisr(),
* mainly to help FreeRTOS, where calls differ between task level and ISR level.
*
* @param msg pointer to the message to post
* @return sys_mbox_trypost_fromisr() return code (without change, so this
* knowledge can be used to e.g. propagate "bool needs_scheduling")
*
* @see tcpip_callbackmsg_new()
*/
err_t
tcpip_callbackmsg_trycallback_fromisr(struct tcpip_callback_msg *msg)
{
LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(tcpip_mbox));
return sys_mbox_trypost_fromisr(&tcpip_mbox, msg);
}
/**
* @ingroup lwip_os
* Initialize this module:
* - initialize all sub modules
* - start the tcpip_thread
*
* @param initfunc a function to call when tcpip_thread is running and finished initializing
* @param arg argument to pass to initfunc
*/
void
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
lwip_init();
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
if (sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
}
#if LWIP_TCPIP_CORE_LOCKING
if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
}
#endif /* LWIP_TCPIP_CORE_LOCKING */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
}
/**
* Simple callback function used with tcpip_callback to free a pbuf
* (pbuf_free has a wrong signature for tcpip_callback)
*
* @param p The pbuf (chain) to be dereferenced.
*/
static void
pbuf_free_int(void *p)
{
struct pbuf *q = (struct pbuf *)p;
pbuf_free(q);
}
/**
* A simple wrapper function that allows you to free a pbuf from interrupt context.
*
* @param p The pbuf (chain) to be dereferenced.
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
err_t
pbuf_free_callback(struct pbuf *p)
{
return tcpip_try_callback(pbuf_free_int, p);
}
/**
* A simple wrapper function that allows you to free heap memory from
* interrupt context.
*
* @param m the heap memory to free
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
err_t
mem_free_callback(void *m)
{
return tcpip_try_callback(mem_free, m);
}
#endif /* !NO_SYS */
+240
View File
@@ -0,0 +1,240 @@
/**
* @file
* Common functions used throughout the stack.
*
* These are reference implementations of the byte swapping functions.
* Again with the aim of being simple, correct and fully portable.
* Byte swapping is the second thing you would want to optimize. You will
* need to port it to your architecture and in your cc.h:
*
* \#define lwip_htons(x) your_htons
* \#define lwip_htonl(x) your_htonl
*
* Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts.
*
* If you \#define them to htons() and htonl(), you should
* \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
* defining htonx/ntohx compatibility macros.
* @defgroup sys_nonstandard Non-standard functions
* @ingroup sys_layer
* lwIP provides default implementations for non-standard functions.
* These can be mapped to OS functions to reduce code footprint if desired.
* All defines related to this section must not be placed in lwipopts.h,
* but in arch/cc.h!
* These options cannot be \#defined in lwipopts.h since they are not options
* of lwIP itself, but options of the lwIP port to your system.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include <string.h>
#if BYTE_ORDER == LITTLE_ENDIAN
#if !defined(lwip_htons)
/**
* Convert an u16_t from host- to network byte order.
*
* @param n u16_t in host byte order
* @return n in network byte order
*/
u16_t
lwip_htons(u16_t n)
{
return PP_HTONS(n);
}
#endif /* lwip_htons */
#if !defined(lwip_htonl)
/**
* Convert an u32_t from host- to network byte order.
*
* @param n u32_t in host byte order
* @return n in network byte order
*/
u32_t
lwip_htonl(u32_t n)
{
return PP_HTONL(n);
}
#endif /* lwip_htonl */
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#ifndef lwip_strnstr
/**
* @ingroup sys_nonstandard
* lwIP default implementation for strnstr() non-standard function.
* This can be \#defined to strnstr() depending on your platform port.
*/
char *
lwip_strnstr(const char *buffer, const char *token, size_t n)
{
const char *p;
size_t tokenlen = strlen(token);
if (tokenlen == 0) {
return LWIP_CONST_CAST(char *, buffer);
}
for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
return LWIP_CONST_CAST(char *, p);
}
}
return NULL;
}
#endif
#ifndef lwip_stricmp
/**
* @ingroup sys_nonstandard
* lwIP default implementation for stricmp() non-standard function.
* This can be \#defined to stricmp() depending on your platform port.
*/
int
lwip_stricmp(const char *str1, const char *str2)
{
char c1, c2;
do {
c1 = *str1++;
c2 = *str2++;
if (c1 != c2) {
char c1_upc = c1 | 0x20;
if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
/* characters are not equal an one is in the alphabet range:
downcase both chars and check again */
char c2_upc = c2 | 0x20;
if (c1_upc != c2_upc) {
/* still not equal */
/* don't care for < or > */
return 1;
}
} else {
/* characters are not equal but none is in the alphabet range */
return 1;
}
}
} while (c1 != 0);
return 0;
}
#endif
#ifndef lwip_strnicmp
/**
* @ingroup sys_nonstandard
* lwIP default implementation for strnicmp() non-standard function.
* This can be \#defined to strnicmp() depending on your platform port.
*/
int
lwip_strnicmp(const char *str1, const char *str2, size_t len)
{
char c1, c2;
do {
c1 = *str1++;
c2 = *str2++;
if (c1 != c2) {
char c1_upc = c1 | 0x20;
if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
/* characters are not equal an one is in the alphabet range:
downcase both chars and check again */
char c2_upc = c2 | 0x20;
if (c1_upc != c2_upc) {
/* still not equal */
/* don't care for < or > */
return 1;
}
} else {
/* characters are not equal but none is in the alphabet range */
return 1;
}
}
len--;
} while ((len != 0) && (c1 != 0));
return 0;
}
#endif
#ifndef lwip_itoa
/**
* @ingroup sys_nonstandard
* lwIP default implementation for itoa() non-standard function.
* This can be \#defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform port.
*/
void
lwip_itoa(char *result, size_t bufsize, int number)
{
char *res = result;
char *tmp = result + bufsize - 1;
int n = (number >= 0) ? number : -number;
/* handle invalid bufsize */
if (bufsize < 2) {
if (bufsize == 1) {
*result = 0;
}
return;
}
/* First, add sign */
if (number < 0) {
*res++ = '-';
}
/* Then create the string from the end and stop if buffer full,
and ensure output string is zero terminated */
*tmp = 0;
while ((n != 0) && (tmp > res)) {
char val = (char)('0' + (n % 10));
tmp--;
*tmp = val;
n = n / 10;
}
if (n) {
/* buffer is too small */
*result = 0;
return;
}
if (*tmp == 0) {
/* Nothing added? */
*res++ = '0';
*res++ = 0;
return;
}
/* move from temporary buffer to output buffer (sign is not moved) */
memmove(res, tmp, (size_t)((result + bufsize) - tmp));
}
#endif
@@ -0,0 +1,608 @@
/**
* @file
* Internet checksum functions.\n
*
* These are some reference implementations of the checksum algorithm, with the
* aim of being simple, correct and fully portable. Checksumming is the
* first thing you would want to optimize for your platform. If you create
* your own version, link it in and in your cc.h put:
*
* \#define LWIP_CHKSUM your_checksum_routine
*
* Or you can select from the implementations below by defining
* LWIP_CHKSUM_ALGORITHM to 1, 2 or 3.
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#include "lwip/inet_chksum.h"
#include "lwip/def.h"
#include "lwip/ip_addr.h"
#include <string.h>
#ifndef LWIP_CHKSUM
# define LWIP_CHKSUM lwip_standard_chksum
# ifndef LWIP_CHKSUM_ALGORITHM
# define LWIP_CHKSUM_ALGORITHM 2
# endif
u16_t lwip_standard_chksum(const void *dataptr, int len);
#endif
/* If none set: */
#ifndef LWIP_CHKSUM_ALGORITHM
# define LWIP_CHKSUM_ALGORITHM 0
#endif
#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
/**
* lwip checksum
*
* @param dataptr points to start of data to be summed at any boundary
* @param len length of data to be summed
* @return host order (!) lwip checksum (non-inverted Internet sum)
*
* @note accumulator size limits summable length to 64k
* @note host endianess is irrelevant (p3 RFC1071)
*/
u16_t
lwip_standard_chksum(const void *dataptr, int len)
{
u32_t acc;
u16_t src;
const u8_t *octetptr;
acc = 0;
/* dataptr may be at odd or even addresses */
octetptr = (const u8_t *)dataptr;
while (len > 1) {
/* declare first octet as most significant
thus assume network order, ignoring host order */
src = (*octetptr) << 8;
octetptr++;
/* declare second octet as least significant */
src |= (*octetptr);
octetptr++;
acc += src;
len -= 2;
}
if (len > 0) {
/* accumulate remaining octet */
src = (*octetptr) << 8;
acc += src;
}
/* add deferred carry bits */
acc = (acc >> 16) + (acc & 0x0000ffffUL);
if ((acc & 0xffff0000UL) != 0) {
acc = (acc >> 16) + (acc & 0x0000ffffUL);
}
/* This maybe a little confusing: reorder sum using lwip_htons()
instead of lwip_ntohs() since it has a little less call overhead.
The caller must invert bits for Internet sum ! */
return lwip_htons((u16_t)acc);
}
#endif
#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */
/*
* Curt McDowell
* Broadcom Corp.
* csm@broadcom.com
*
* IP checksum two bytes at a time with support for
* unaligned buffer.
* Works for len up to and including 0x20000.
* by Curt McDowell, Broadcom Corp. 12/08/2005
*
* @param dataptr points to start of data to be summed at any boundary
* @param len length of data to be summed
* @return host order (!) lwip checksum (non-inverted Internet sum)
*/
u16_t
lwip_standard_chksum(const void *dataptr, int len)
{
const u8_t *pb = (const u8_t *)dataptr;
const u16_t *ps;
u16_t t = 0;
u32_t sum = 0;
int odd = ((mem_ptr_t)pb & 1);
/* Get aligned to u16_t */
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
/* Add the bulk of the data */
ps = (const u16_t *)(const void *)pb;
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* Consume left-over byte, if any */
if (len > 0) {
((u8_t *)&t)[0] = *(const u8_t *)ps;
}
/* Add end bytes */
sum += t;
/* Fold 32-bit sum to 16 bits
calling this twice is probably faster than if statements... */
sum = FOLD_U32T(sum);
sum = FOLD_U32T(sum);
/* Swap if alignment was odd */
if (odd) {
sum = SWAP_BYTES_IN_WORD(sum);
}
return (u16_t)sum;
}
#endif
#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */
/**
* An optimized checksum routine. Basically, it uses loop-unrolling on
* the checksum loop, treating the head and tail bytes specially, whereas
* the inner loop acts on 8 bytes at a time.
*
* @arg start of buffer to be checksummed. May be an odd byte address.
* @len number of bytes in the buffer to be checksummed.
* @return host order (!) lwip checksum (non-inverted Internet sum)
*
* by Curt McDowell, Broadcom Corp. December 8th, 2005
*/
u16_t
lwip_standard_chksum(const void *dataptr, int len)
{
const u8_t *pb = (const u8_t *)dataptr;
const u16_t *ps;
u16_t t = 0;
const u32_t *pl;
u32_t sum = 0, tmp;
/* starts at odd byte address? */
int odd = ((mem_ptr_t)pb & 1);
if (odd && len > 0) {
((u8_t *)&t)[1] = *pb++;
len--;
}
ps = (const u16_t *)(const void *)pb;
if (((mem_ptr_t)ps & 3) && len > 1) {
sum += *ps++;
len -= 2;
}
pl = (const u32_t *)(const void *)ps;
while (len > 7) {
tmp = sum + *pl++; /* ping */
if (tmp < sum) {
tmp++; /* add back carry */
}
sum = tmp + *pl++; /* pong */
if (sum < tmp) {
sum++; /* add back carry */
}
len -= 8;
}
/* make room in upper bits */
sum = FOLD_U32T(sum);
ps = (const u16_t *)pl;
/* 16-bit aligned word remaining? */
while (len > 1) {
sum += *ps++;
len -= 2;
}
/* dangling tail byte remaining? */
if (len > 0) { /* include odd byte */
((u8_t *)&t)[0] = *(const u8_t *)ps;
}
sum += t; /* add end bytes */
/* Fold 32-bit sum to 16 bits
calling this twice is probably faster than if statements... */
sum = FOLD_U32T(sum);
sum = FOLD_U32T(sum);
if (odd) {
sum = SWAP_BYTES_IN_WORD(sum);
}
return (u16_t)sum;
}
#endif
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
static u16_t
inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc)
{
struct pbuf *q;
int swapped = 0;
/* iterate through all pbuf in chain */
for (q = p; q != NULL; q = q->next) {
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
(void *)q, (void *)q->next));
acc += LWIP_CHKSUM(q->payload, q->len);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
/* just executing this next line is probably faster that the if statement needed
to check whether we really need to execute it, and does no harm */
acc = FOLD_U32T(acc);
if (q->len % 2 != 0) {
swapped = !swapped;
acc = SWAP_BYTES_IN_WORD(acc);
}
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
}
if (swapped) {
acc = SWAP_BYTES_IN_WORD(acc);
}
acc += (u32_t)lwip_htons((u16_t)proto);
acc += (u32_t)lwip_htons(proto_len);
/* Fold 32-bit sum to 16 bits
calling this twice is probably faster than if statements... */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
return (u16_t)~(acc & 0xffffUL);
}
#if LWIP_IPV4
/* inet_chksum_pseudo:
*
* Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
* IP addresses are expected to be in network byte order.
*
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
* @param src source ip address (used for checksum of pseudo header)
* @param dst destination ip address (used for checksum of pseudo header)
* @param proto ip protocol (used for checksum of pseudo header)
* @param proto_len length of the ip data part (used for checksum of pseudo header)
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
const ip4_addr_t *src, const ip4_addr_t *dest)
{
u32_t acc;
u32_t addr;
addr = ip4_addr_get_u32(src);
acc = (addr & 0xffffUL);
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
addr = ip4_addr_get_u32(dest);
acc = (u32_t)(acc + (addr & 0xffffUL));
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
/* fold down to 16 bits */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
}
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
/**
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
* IPv6 addresses are expected to be in network byte order.
*
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
* @param src source ipv6 address (used for checksum of pseudo header)
* @param dest destination ipv6 address (used for checksum of pseudo header)
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
const ip6_addr_t *src, const ip6_addr_t *dest)
{
u32_t acc = 0;
u32_t addr;
u8_t addr_part;
for (addr_part = 0; addr_part < 4; addr_part++) {
addr = src->addr[addr_part];
acc = (u32_t)(acc + (addr & 0xffffUL));
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
addr = dest->addr[addr_part];
acc = (u32_t)(acc + (addr & 0xffffUL));
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
}
/* fold down to 16 bits */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
return inet_cksum_pseudo_base(p, proto, proto_len, acc);
}
#endif /* LWIP_IPV6 */
/* ip_chksum_pseudo:
*
* Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
* IP addresses are expected to be in network byte order.
*
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
* @param src source ip address (used for checksum of pseudo header)
* @param dst destination ip address (used for checksum of pseudo header)
* @param proto ip protocol (used for checksum of pseudo header)
* @param proto_len length of the ip data part (used for checksum of pseudo header)
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
const ip_addr_t *src, const ip_addr_t *dest)
{
#if LWIP_IPV6
if (IP_IS_V6(dest)) {
return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest));
}
#endif /* LWIP_IPV6 */
#if LWIP_IPV4 && LWIP_IPV6
else
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if LWIP_IPV4
{
return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest));
}
#endif /* LWIP_IPV4 */
}
/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
static u16_t
inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len,
u16_t chksum_len, u32_t acc)
{
struct pbuf *q;
int swapped = 0;
u16_t chklen;
/* iterate through all pbuf in chain */
for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
(void *)q, (void *)q->next));
chklen = q->len;
if (chklen > chksum_len) {
chklen = chksum_len;
}
acc += LWIP_CHKSUM(q->payload, chklen);
chksum_len = (u16_t)(chksum_len - chklen);
LWIP_ASSERT("delete me", chksum_len < 0x7fff);
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
/* fold the upper bit down */
acc = FOLD_U32T(acc);
if (q->len % 2 != 0) {
swapped = !swapped;
acc = SWAP_BYTES_IN_WORD(acc);
}
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
}
if (swapped) {
acc = SWAP_BYTES_IN_WORD(acc);
}
acc += (u32_t)lwip_htons((u16_t)proto);
acc += (u32_t)lwip_htons(proto_len);
/* Fold 32-bit sum to 16 bits
calling this twice is probably faster than if statements... */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
return (u16_t)~(acc & 0xffffUL);
}
#if LWIP_IPV4
/* inet_chksum_pseudo_partial:
*
* Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
* IP addresses are expected to be in network byte order.
*
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
* @param src source ip address (used for checksum of pseudo header)
* @param dst destination ip address (used for checksum of pseudo header)
* @param proto ip protocol (used for checksum of pseudo header)
* @param proto_len length of the ip data part (used for checksum of pseudo header)
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest)
{
u32_t acc;
u32_t addr;
addr = ip4_addr_get_u32(src);
acc = (addr & 0xffffUL);
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
addr = ip4_addr_get_u32(dest);
acc = (u32_t)(acc + (addr & 0xffffUL));
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
/* fold down to 16 bits */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
}
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
/**
* Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
* IPv6 addresses are expected to be in network byte order. Will only compute for a
* portion of the payload.
*
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
* @param proto ipv6 protocol/next header (used for checksum of pseudo header)
* @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
* @param chksum_len number of payload bytes used to compute chksum
* @param src source ipv6 address (used for checksum of pseudo header)
* @param dest destination ipv6 address (used for checksum of pseudo header)
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest)
{
u32_t acc = 0;
u32_t addr;
u8_t addr_part;
for (addr_part = 0; addr_part < 4; addr_part++) {
addr = src->addr[addr_part];
acc = (u32_t)(acc + (addr & 0xffffUL));
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
addr = dest->addr[addr_part];
acc = (u32_t)(acc + (addr & 0xffffUL));
acc = (u32_t)(acc + ((addr >> 16) & 0xffffUL));
}
/* fold down to 16 bits */
acc = FOLD_U32T(acc);
acc = FOLD_U32T(acc);
return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
}
#endif /* LWIP_IPV6 */
/* ip_chksum_pseudo_partial:
*
* Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
*
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
* @param src source ip address (used for checksum of pseudo header)
* @param dst destination ip address (used for checksum of pseudo header)
* @param proto ip protocol (used for checksum of pseudo header)
* @param proto_len length of the ip data part (used for checksum of pseudo header)
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest)
{
#if LWIP_IPV6
if (IP_IS_V6(dest)) {
return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest));
}
#endif /* LWIP_IPV6 */
#if LWIP_IPV4 && LWIP_IPV6
else
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if LWIP_IPV4
{
return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest));
}
#endif /* LWIP_IPV4 */
}
/* inet_chksum:
*
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
* and ICMP.
*
* @param dataptr start of the buffer to calculate the checksum (no alignment needed)
* @param len length of the buffer to calculate the checksum
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
inet_chksum(const void *dataptr, u16_t len)
{
return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len);
}
/**
* Calculate a checksum over a chain of pbufs (without pseudo-header, much like
* inet_chksum only pbufs are used).
*
* @param p pbuf chain over that the checksum should be calculated
* @return checksum (as u16_t) to be saved directly in the protocol header
*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
u32_t acc;
struct pbuf *q;
int swapped = 0;
acc = 0;
for (q = p; q != NULL; q = q->next) {
acc += LWIP_CHKSUM(q->payload, q->len);
acc = FOLD_U32T(acc);
if (q->len % 2 != 0) {
swapped = !swapped;
acc = SWAP_BYTES_IN_WORD(acc);
}
}
if (swapped) {
acc = SWAP_BYTES_IN_WORD(acc);
}
return (u16_t)~(acc & 0xffffUL);
}
/* These are some implementations for LWIP_CHKSUM_COPY, which copies data
* like MEMCPY but generates a checksum at the same time. Since this is a
* performance-sensitive function, you might want to create your own version
* in assembly targeted at your hardware by defining it in lwipopts.h:
* #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len)
*/
#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */
/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM.
* For architectures with big caches, data might still be in cache when
* generating the checksum after copying.
*/
u16_t
lwip_chksum_copy(void *dst, const void *src, u16_t len)
{
MEMCPY(dst, src, len);
return LWIP_CHKSUM(dst, len);
}
#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */
+380
View File
@@ -0,0 +1,380 @@
/**
* @file
* Modules initialization
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*/
#include "lwip/opt.h"
#include "lwip/init.h"
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"
#include "lwip/netif.h"
#include "lwip/sockets.h"
#include "lwip/ip.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/igmp.h"
#include "lwip/dns.h"
#include "lwip/timeouts.h"
#include "lwip/etharp.h"
#include "lwip/ip6.h"
#include "lwip/nd6.h"
#include "lwip/mld6.h"
#include "lwip/api.h"
#include "netif/ppp/ppp_opts.h"
#include "netif/ppp/ppp_impl.h"
#ifndef LWIP_SKIP_PACKING_CHECK
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct packed_struct_test {
PACK_STRUCT_FLD_8(u8_t dummy1);
PACK_STRUCT_FIELD(u32_t dummy2);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5
#endif
/* Compile-time sanity checks for configuration errors.
* These can be done independently of LWIP_DEBUG, without penalty.
*/
#ifndef BYTE_ORDER
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
#endif
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && LWIP_UDPLITE)
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && LWIP_DHCP)
#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && !LWIP_RAW && LWIP_MULTICAST_TX_OPTIONS)
#error "If you want to use LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 and/or LWIP_RAW=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && LWIP_DNS)
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
#endif
#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
#endif
#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
#endif
#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
#endif
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
#endif
#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS)
#error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
#endif
#if (LWIP_IGMP && !LWIP_IPV4)
#error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
#endif
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
#endif
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < LWIP_NUM_SYS_TIMEOUT_INTERNAL)
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
#endif
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
#endif
#endif /* !MEMP_MEM_MALLOC */
#if LWIP_WND_SCALE
#if (LWIP_TCP && (TCP_WND > 0xffffffff))
#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
#endif
#if (LWIP_TCP && (TCP_RCV_SCALE > 14))
#error "The maximum valid window scale value is 14!"
#endif
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
#endif
#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
#endif
#else /* LWIP_WND_SCALE */
#if (LWIP_TCP && (TCP_WND > 0xffff))
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
#endif
#endif /* LWIP_WND_SCALE */
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
#endif
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
#endif
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
#endif
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)))
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
#endif
#if (LWIP_TCP && LWIP_TCP_SACK_OUT && !TCP_QUEUE_OOSEQ)
#error "To use LWIP_TCP_SACK_OUT, TCP_QUEUE_OOSEQ needs to be enabled"
#endif
#if (LWIP_TCP && LWIP_TCP_SACK_OUT && (LWIP_TCP_MAX_SACK_NUM < 1))
#error "LWIP_TCP_MAX_SACK_NUM must be greater than 0"
#endif
#if (LWIP_NETIF_API && (NO_SYS==1))
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
#if (LWIP_PPP_API && (NO_SYS==1))
#error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
#if (LWIP_PPP_API && (PPP_SUPPORT==0))
#error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
#endif
#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
#endif
#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
#endif
#if (!LWIP_ARP && LWIP_AUTOIP)
#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
#endif
#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
#endif
#if (LWIP_ALTCP && LWIP_EVENT_API)
#error "The application layered tcp API does not work with LWIP_EVENT_API"
#endif
#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
#endif
#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
#endif
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
#endif
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
#endif
#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT
#error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
#endif
#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT
#error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
#endif
#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4
#error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
#endif
#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6
#error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
#endif
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
#endif
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
#endif
#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
#error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
#endif
#if LWIP_NETCONN && LWIP_TCP
#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
#error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
#endif
#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
#endif
#endif /* LWIP_NETCONN && LWIP_TCP */
#if LWIP_SOCKET
#endif /* LWIP_SOCKET */
/* Compile-time checks for deprecated options.
*/
#ifdef MEMP_NUM_TCPIP_MSG
#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef TCP_REXMIT_DEBUG
#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef RAW_STATS
#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef ETHARP_QUEUE_FIRST
#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef ETHARP_ALWAYS_INSERT
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
#endif
#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED)
#error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)"
#endif
#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
#define LWIP_DISABLE_TCP_SANITY_CHECKS 0
#endif
#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS
#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0
#endif
/* MEMP sanity checks */
#if MEMP_MEM_MALLOC
#if !LWIP_DISABLE_MEMP_SANITY_CHECKS
#if LWIP_NETCONN || LWIP_SOCKET
#if !MEMP_NUM_NETCONN && LWIP_SOCKET
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!"
#endif
#else /* MEMP_MEM_MALLOC */
#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error."
#endif
#endif /* LWIP_NETCONN || LWIP_SOCKET */
#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */
#if MEM_USE_POOLS
#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time"
#endif
#ifdef LWIP_HOOK_MEMP_AVAILABLE
#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC"
#endif
#endif /* MEMP_MEM_MALLOC */
/* TCP sanity checks */
#if !LWIP_DISABLE_TCP_SANITY_CHECKS
#if LWIP_TCP
#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SND_BUF < (2 * TCP_MSS)
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
#error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SNDLOWAT >= TCP_SND_BUF
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
#endif
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
#error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
#error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
#error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_WND < TCP_MSS
#error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#endif /* LWIP_TCP */
#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
/**
* @ingroup lwip_nosys
* Initialize all modules.
* Use this in NO_SYS mode. Use tcpip_init() otherwise.
*/
void
lwip_init(void)
{
#ifndef LWIP_SKIP_CONST_CHECK
int a = 0;
LWIP_UNUSED_ARG(a);
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void *, &a) == &a);
#endif
#ifndef LWIP_SKIP_PACKING_CHECK
LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
#endif
/* Modules initialization */
stats_init();
#if !NO_SYS
sys_init();
#endif /* !NO_SYS */
mem_init();
memp_init();
pbuf_init();
netif_init();
#if LWIP_IPV4
ip_init();
#if LWIP_ARP
etharp_init();
#endif /* LWIP_ARP */
#endif /* LWIP_IPV4 */
#if LWIP_RAW
raw_init();
#endif /* LWIP_RAW */
#if LWIP_UDP
udp_init();
#endif /* LWIP_UDP */
#if LWIP_TCP
tcp_init();
#endif /* LWIP_TCP */
#if LWIP_IGMP
igmp_init();
#endif /* LWIP_IGMP */
#if LWIP_DNS
dns_init();
#endif /* LWIP_DNS */
#if PPP_SUPPORT
ppp_init();
#endif
#if LWIP_TIMERS
sys_timeouts_init();
#endif /* LWIP_TIMERS */
}
+167
View File
@@ -0,0 +1,167 @@
/**
* @file
* Common IPv4 and IPv6 code
*
* @defgroup ip IP
* @ingroup callbackstyle_api
*
* @defgroup ip4 IPv4
* @ingroup ip
*
* @defgroup ip6 IPv6
* @ingroup ip
*
* @defgroup ipaddr IP address handling
* @ingroup infrastructure
*
* @defgroup ip4addr IPv4 only
* @ingroup ipaddr
*
* @defgroup ip6addr IPv6 only
* @ingroup ipaddr
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if LWIP_IPV4 || LWIP_IPV6
#include "lwip/ip_addr.h"
#include "lwip/ip.h"
/** Global data for both IPv4 and IPv6 */
struct ip_globals ip_data;
#if LWIP_IPV4 && LWIP_IPV6
const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT;
/**
* @ingroup ipaddr
* Convert numeric IP address (both versions) into ASCII representation.
* returns ptr to static buffer; not reentrant!
*
* @param addr ip address in network order to convert
* @return pointer to a global static (!) buffer that holds the ASCII
* representation of addr
*/
char *ipaddr_ntoa(const ip_addr_t *addr)
{
if (addr == NULL) {
return NULL;
}
if (IP_IS_V6(addr)) {
return ip6addr_ntoa(ip_2_ip6(addr));
} else {
return ip4addr_ntoa(ip_2_ip4(addr));
}
}
/**
* @ingroup ipaddr
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
*
* @param addr ip address in network order to convert
* @param buf target buffer where the string is stored
* @param buflen length of buf
* @return either pointer to buf which now holds the ASCII
* representation of addr or NULL if buf was too small
*/
char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)
{
if (addr == NULL) {
return NULL;
}
if (IP_IS_V6(addr)) {
return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
} else {
return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
}
}
/**
* @ingroup ipaddr
* Convert IP address string (both versions) to numeric.
* The version is auto-detected from the string.
*
* @param cp IP address string to convert
* @param addr conversion result is stored here
* @return 1 on success, 0 on error
*/
int
ipaddr_aton(const char *cp, ip_addr_t *addr)
{
if (cp != NULL) {
const char *c;
for (c = cp; *c != 0; c++) {
if (*c == ':') {
/* contains a colon: IPv6 address */
if (addr) {
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6);
}
return ip6addr_aton(cp, ip_2_ip6(addr));
} else if (*c == '.') {
/* contains a dot: IPv4 address */
break;
}
}
/* call ip4addr_aton as fallback or if IPv4 was found */
if (addr) {
IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4);
}
return ip4addr_aton(cp, ip_2_ip4(addr));
}
return 0;
}
/**
* @ingroup lwip_nosys
* If both IP versions are enabled, this function can dispatch packets to the correct one.
* Don't call directly, pass to netif_add() and call netif->input().
*/
err_t
ip_input(struct pbuf *p, struct netif *inp)
{
if (p != NULL) {
if (IP_HDR_GET_VERSION(p->payload) == 6) {
return ip6_input(p, inp);
}
return ip4_input(p, inp);
}
return ERR_VAL;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#endif /* LWIP_IPV4 || LWIP_IPV6 */
@@ -0,0 +1,527 @@
/**
* @file
* AutoIP Automatic LinkLocal IP Configuration
*
* This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
* with RFC 3927.
*
* @defgroup autoip AUTOIP
* @ingroup ip4
* AUTOIP related functions
* USAGE:
*
* define @ref LWIP_AUTOIP 1 in your lwipopts.h
* Options:
* AUTOIP_TMR_INTERVAL msecs,
* I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
* Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
*
* Without DHCP:
* - Call autoip_start() after netif_add().
*
* With DHCP:
* - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
* - Configure your DHCP Client.
*
* @see netifapi_autoip
*/
/*
*
* Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dominik Spies <kontakt@dspies.de>
*/
#include "lwip/opt.h"
#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
#include "lwip/mem.h"
/* #include "lwip/udp.h" */
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/autoip.h"
#include "lwip/etharp.h"
#include "lwip/prot/autoip.h"
#include <string.h>
/** Pseudo random macro based on netif informations.
* You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */
#ifndef LWIP_AUTOIP_RAND
#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
((u32_t)((netif->hwaddr[4]) & 0xff))) + \
(netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0))
#endif /* LWIP_AUTOIP_RAND */
/**
* Macro that generates the initial IP address to be tried by AUTOIP.
* If you want to override this, define it to something else in lwipopts.h.
*/
#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
/* static functions */
static err_t autoip_arp_announce(struct netif *netif);
static void autoip_start_probing(struct netif *netif);
/**
* @ingroup autoip
* Set a statically allocated struct autoip to work with.
* Using this prevents autoip_start to allocate it using mem_malloc.
*
* @param netif the netif for which to set the struct autoip
* @param autoip (uninitialised) autoip struct allocated by the application
*/
void
autoip_set_struct(struct netif *netif, struct autoip *autoip)
{
LWIP_ASSERT_CORE_LOCKED();
LWIP_ASSERT("netif != NULL", netif != NULL);
LWIP_ASSERT("autoip != NULL", autoip != NULL);
LWIP_ASSERT("netif already has a struct autoip set",
netif_autoip_data(netif) == NULL);
/* clear data structure */
memset(autoip, 0, sizeof(struct autoip));
/* autoip->state = AUTOIP_STATE_OFF; */
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
}
/** Restart AutoIP client and check the next address (conflict detected)
*
* @param netif The netif under AutoIP control
*/
static void
autoip_restart(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
autoip->tried_llipaddr++;
autoip_start(netif);
}
/**
* Handle a IP address conflict after an ARP conflict detection
*/
static void
autoip_handle_arp_conflict(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
/* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where
a) means retreat on the first conflict and
b) allows to keep an already configured address when having only one
conflict in 10 seconds
We use option b) since it helps to improve the chance that one of the two
conflicting hosts may be able to retain its address. */
if (autoip->lastconflict > 0) {
/* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
/* Active TCP sessions are aborted when removing the ip addresss */
autoip_restart(netif);
} else {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
autoip_arp_announce(netif);
autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
}
}
/**
* Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
*
* @param netif network interface on which create the IP-Address
* @param ipaddr ip address to initialize
*/
static void
autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr)
{
struct autoip *autoip = netif_autoip_data(netif);
/* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
* compliant to RFC 3927 Section 2.1
* We have 254 * 256 possibilities */
u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
addr += autoip->tried_llipaddr;
addr = AUTOIP_NET | (addr & 0xffff);
/* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
if (addr < AUTOIP_RANGE_START) {
addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
}
if (addr > AUTOIP_RANGE_END) {
addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
}
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
(addr <= AUTOIP_RANGE_END));
ip4_addr_set_u32(ipaddr, lwip_htonl(addr));
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
(u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
}
/**
* Sends an ARP probe from a network interface
*
* @param netif network interface used to send the probe
*/
static err_t
autoip_arp_probe(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
/* this works because netif->ip_addr is ANY */
return etharp_request(netif, &autoip->llipaddr);
}
/**
* Sends an ARP announce from a network interface
*
* @param netif network interface used to send the announce
*/
static err_t
autoip_arp_announce(struct netif *netif)
{
return etharp_gratuitous(netif);
}
/**
* Configure interface for use with current LL IP-Address
*
* @param netif network interface to configure with current LL IP-Address
*/
static err_t
autoip_bind(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
ip4_addr_t sn_mask, gw_addr;
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
(void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
IP4_ADDR(&sn_mask, 255, 255, 0, 0);
IP4_ADDR(&gw_addr, 0, 0, 0, 0);
netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr);
/* interface is used by routing now that an address is set */
return ERR_OK;
}
/**
* @ingroup autoip
* Start AutoIP client
*
* @param netif network interface on which start the AutoIP client
*/
err_t
autoip_start(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
err_t result = ERR_OK;
LWIP_ASSERT_CORE_LOCKED();
LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
/* Set IP-Address, Netmask and Gateway to 0 to make sure that
* ARP Packets are formed correctly
*/
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void *)netif, netif->name[0],
netif->name[1], (u16_t)netif->num));
if (autoip == NULL) {
/* no AutoIP client attached yet? */
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_start(): starting new AUTOIP client\n"));
autoip = (struct autoip *)mem_calloc(1, sizeof(struct autoip));
if (autoip == NULL) {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_start(): could not allocate autoip\n"));
return ERR_MEM;
}
/* store this AutoIP client in the netif */
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
} else {
autoip->state = AUTOIP_STATE_OFF;
autoip->ttw = 0;
autoip->sent_num = 0;
ip4_addr_set_zero(&autoip->llipaddr);
autoip->lastconflict = 0;
}
autoip_create_addr(netif, &(autoip->llipaddr));
autoip_start_probing(netif);
return result;
}
static void
autoip_start_probing(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
autoip->state = AUTOIP_STATE_PROBING;
autoip->sent_num = 0;
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
/* time to wait to first probe, this is randomly
* chosen out of 0 to PROBE_WAIT seconds.
* compliant to RFC 3927 Section 2.2.1
*/
autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
/*
* if we tried more then MAX_CONFLICTS we must limit our rate for
* acquiring and probing address
* compliant to RFC 3927 Section 2.2.1
*/
if (autoip->tried_llipaddr > MAX_CONFLICTS) {
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
}
}
/**
* Handle a possible change in the network configuration.
*
* If there is an AutoIP address configured, take the interface down
* and begin probing with the same address.
*/
void
autoip_network_changed(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
if (autoip && (autoip->state != AUTOIP_STATE_OFF)) {
autoip_start_probing(netif);
}
}
/**
* @ingroup autoip
* Stop AutoIP client
*
* @param netif network interface on which stop the AutoIP client
*/
err_t
autoip_stop(struct netif *netif)
{
struct autoip *autoip = netif_autoip_data(netif);
LWIP_ASSERT_CORE_LOCKED();
if (autoip != NULL) {
autoip->state = AUTOIP_STATE_OFF;
if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
}
}
return ERR_OK;
}
/**
* Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds
*/
void
autoip_tmr(void)
{
struct netif *netif;
/* loop through netif's */
NETIF_FOREACH(netif) {
struct autoip *autoip = netif_autoip_data(netif);
/* only act on AutoIP configured interfaces */
if (autoip != NULL) {
if (autoip->lastconflict > 0) {
autoip->lastconflict--;
}
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
(u16_t)(autoip->state), autoip->ttw));
if (autoip->ttw > 0) {
autoip->ttw--;
}
switch (autoip->state) {
case AUTOIP_STATE_PROBING:
if (autoip->ttw == 0) {
if (autoip->sent_num >= PROBE_NUM) {
/* Switch to ANNOUNCING: now we can bind to an IP address and use it */
autoip->state = AUTOIP_STATE_ANNOUNCING;
autoip_bind(netif);
/* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP
which counts as an announcement */
autoip->sent_num = 1;
autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
} else {
autoip_arp_probe(netif);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n"));
autoip->sent_num++;
if (autoip->sent_num == PROBE_NUM) {
/* calculate time to wait to for announce */
autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
} else {
/* calculate time to wait to next probe */
autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
}
}
}
break;
case AUTOIP_STATE_ANNOUNCING:
if (autoip->ttw == 0) {
autoip_arp_announce(netif);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n"));
autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
autoip->sent_num++;
if (autoip->sent_num >= ANNOUNCE_NUM) {
autoip->state = AUTOIP_STATE_BOUND;
autoip->sent_num = 0;
autoip->ttw = 0;
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
}
}
break;
default:
/* nothing to do in other states */
break;
}
}
}
}
/**
* Handles every incoming ARP Packet, called by etharp_input().
*
* @param netif network interface to use for autoip processing
* @param hdr Incoming ARP packet
*/
void
autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
{
struct autoip *autoip = netif_autoip_data(netif);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) {
/* when ip.src == llipaddr && hw.src != netif->hwaddr
*
* when probing ip.dst == llipaddr && hw.src != netif->hwaddr
* we have a conflict and must solve it
*/
ip4_addr_t sipaddr, dipaddr;
struct eth_addr netifaddr;
SMEMCPY(netifaddr.addr, netif->hwaddr, ETH_HWADDR_LEN);
/* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without
* structure packing (not using structure copy which breaks strict-aliasing rules).
*/
IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr);
IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &hdr->dipaddr);
if (autoip->state == AUTOIP_STATE_PROBING) {
/* RFC 3927 Section 2.2.1:
* from beginning to after ANNOUNCE_WAIT
* seconds we have a conflict if
* ip.src == llipaddr OR
* ip.dst == llipaddr && hw.src != own hwaddr
*/
if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
(ip4_addr_isany_val(sipaddr) &&
ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
("autoip_arp_reply(): Probe Conflict detected\n"));
autoip_restart(netif);
}
} else {
/* RFC 3927 Section 2.5:
* in any state we have a conflict if
* ip.src == llipaddr && hw.src != own hwaddr
*/
if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) &&
!eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
autoip_handle_arp_conflict(netif);
}
}
}
}
/** check if AutoIP supplied netif->ip_addr
*
* @param netif the netif to check
* @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING),
* 0 otherwise
*/
u8_t
autoip_supplied_address(const struct netif *netif)
{
if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) {
struct autoip *autoip = netif_autoip_data(netif);
return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING);
}
return 0;
}
u8_t
autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr)
{
struct autoip *autoip = netif_autoip_data(netif);
return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr));
}
#endif /* LWIP_IPV4 && LWIP_AUTOIP */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,404 @@
/**
* @file
* ICMP - Internet Control Message Protocol
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/* Some ICMP messages should be passed to the transport protocols. This
is not implemented. */
#include "lwip/opt.h"
#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/icmp.h"
#include "lwip/inet_chksum.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/stats.h"
#include <string.h>
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
* used to modify and send a response packet (and to 1 if this is not the case,
* e.g. when link header is stripped off when receiving) */
#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
/* The amount of data from the original packet to return in a dest-unreachable */
#define ICMP_DEST_UNREACH_DATASIZE 8
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
/**
* Processes ICMP input packets, called from ip_input().
*
* Currently only processes icmp echo requests and sends
* out the echo response.
*
* @param p the icmp echo request packet, p->payload pointing to the icmp header
* @param inp the netif on which this packet was received
*/
void
icmp_input(struct pbuf *p, struct netif *inp)
{
u8_t type;
#ifdef LWIP_DEBUG
u8_t code;
#endif /* LWIP_DEBUG */
struct icmp_echo_hdr *iecho;
const struct ip_hdr *iphdr_in;
u16_t hlen;
const ip4_addr_t *src;
ICMP_STATS_INC(icmp.recv);
MIB2_STATS_INC(mib2.icmpinmsgs);
iphdr_in = ip4_current_header();
hlen = IPH_HL_BYTES(iphdr_in);
if (hlen < IP_HLEN) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen));
goto lenerr;
}
if (p->len < sizeof(u16_t) * 2) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
goto lenerr;
}
type = *((u8_t *)p->payload);
#ifdef LWIP_DEBUG
code = *(((u8_t *)p->payload) + 1);
/* if debug is enabled but debug statement below is somehow disabled: */
LWIP_UNUSED_ARG(code);
#endif /* LWIP_DEBUG */
switch (type) {
case ICMP_ER:
/* This is OK, echo reply might have been parsed by a raw PCB
(as obviously, an echo request has been sent, too). */
MIB2_STATS_INC(mib2.icmpinechoreps);
break;
case ICMP_ECHO:
MIB2_STATS_INC(mib2.icmpinechos);
src = ip4_current_dest_addr();
/* multicast destination address? */
if (ip4_addr_ismulticast(ip4_current_dest_addr())) {
#if LWIP_MULTICAST_PING
/* For multicast, use address of receiving interface as source address */
src = netif_ip4_addr(inp);
#else /* LWIP_MULTICAST_PING */
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n"));
goto icmperr;
#endif /* LWIP_MULTICAST_PING */
}
/* broadcast destination address? */
if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) {
#if LWIP_BROADCAST_PING
/* For broadcast, use address of receiving interface as source address */
src = netif_ip4_addr(inp);
#else /* LWIP_BROADCAST_PING */
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n"));
goto icmperr;
#endif /* LWIP_BROADCAST_PING */
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
goto lenerr;
}
#if CHECKSUM_CHECK_ICMP
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) {
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p);
ICMP_STATS_INC(icmp.chkerr);
MIB2_STATS_INC(mib2.icmpinerrors);
return;
}
}
#endif
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
if (pbuf_add_header(p, hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN)) {
/* p is not big enough to contain link headers
* allocate a new one and copy p into it
*/
struct pbuf *r;
u16_t alloc_len = (u16_t)(p->tot_len + hlen);
if (alloc_len < p->tot_len) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed (tot_len overflow)\n"));
goto icmperr;
}
/* allocate new packet buffer with space for link headers */
r = pbuf_alloc(PBUF_LINK, alloc_len, PBUF_RAM);
if (r == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
goto icmperr;
}
if (r->len < hlen + sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header"));
pbuf_free(r);
goto icmperr;
}
/* copy the ip header */
MEMCPY(r->payload, iphdr_in, hlen);
/* switch r->payload back to icmp header (cannot fail) */
if (pbuf_remove_header(r, hlen)) {
LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
pbuf_free(r);
goto icmperr;
}
/* copy the rest of the packet without ip header */
if (pbuf_copy(r, p) != ERR_OK) {
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed"));
pbuf_free(r);
goto icmperr;
}
/* free the original p */
pbuf_free(p);
/* we now have an identical copy of p that has room for link headers */
p = r;
} else {
/* restore p->payload to point to icmp header (cannot fail) */
if (pbuf_remove_header(p, hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN)) {
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
goto icmperr;
}
}
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
/* At this point, all checks are OK. */
/* We generate an answer by switching the dest and src ip addresses,
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
iecho = (struct icmp_echo_hdr *)p->payload;
if (pbuf_add_header(p, hlen)) {
LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet"));
} else {
err_t ret;
struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
ip4_addr_copy(iphdr->src, *src);
ip4_addr_copy(iphdr->dest, *ip4_current_src_addr());
ICMPH_TYPE_SET(iecho, ICMP_ER);
#if CHECKSUM_GEN_ICMP
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) {
/* adjust the checksum */
if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
iecho->chksum = (u16_t)(iecho->chksum + PP_HTONS((u16_t)(ICMP_ECHO << 8)) + 1);
} else {
iecho->chksum = (u16_t)(iecho->chksum + PP_HTONS(ICMP_ECHO << 8));
}
}
#if LWIP_CHECKSUM_CTRL_PER_NETIF
else {
iecho->chksum = 0;
}
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
#else /* CHECKSUM_GEN_ICMP */
iecho->chksum = 0;
#endif /* CHECKSUM_GEN_ICMP */
/* Set the correct TTL and recalculate the header checksum. */
IPH_TTL_SET(iphdr, ICMP_TTL);
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) {
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen));
}
#endif /* CHECKSUM_GEN_IP */
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
MIB2_STATS_INC(mib2.icmpoutmsgs);
/* increase number of echo replies attempted to send */
MIB2_STATS_INC(mib2.icmpoutechoreps);
/* send an ICMP packet */
ret = ip4_output_if(p, src, LWIP_IP_HDRINCL,
ICMP_TTL, 0, IP_PROTO_ICMP, inp);
if (ret != ERR_OK) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret)));
}
}
break;
default:
if (type == ICMP_DUR) {
MIB2_STATS_INC(mib2.icmpindestunreachs);
} else if (type == ICMP_TE) {
MIB2_STATS_INC(mib2.icmpintimeexcds);
} else if (type == ICMP_PP) {
MIB2_STATS_INC(mib2.icmpinparmprobs);
} else if (type == ICMP_SQ) {
MIB2_STATS_INC(mib2.icmpinsrcquenchs);
} else if (type == ICMP_RD) {
MIB2_STATS_INC(mib2.icmpinredirects);
} else if (type == ICMP_TS) {
MIB2_STATS_INC(mib2.icmpintimestamps);
} else if (type == ICMP_TSR) {
MIB2_STATS_INC(mib2.icmpintimestampreps);
} else if (type == ICMP_AM) {
MIB2_STATS_INC(mib2.icmpinaddrmasks);
} else if (type == ICMP_AMR) {
MIB2_STATS_INC(mib2.icmpinaddrmaskreps);
}
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n",
(s16_t)type, (s16_t)code));
ICMP_STATS_INC(icmp.proterr);
ICMP_STATS_INC(icmp.drop);
}
pbuf_free(p);
return;
lenerr:
pbuf_free(p);
ICMP_STATS_INC(icmp.lenerr);
MIB2_STATS_INC(mib2.icmpinerrors);
return;
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
icmperr:
pbuf_free(p);
ICMP_STATS_INC(icmp.err);
MIB2_STATS_INC(mib2.icmpinerrors);
return;
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */
}
/**
* Send an icmp 'destination unreachable' packet, called from ip_input() if
* the transport layer protocol is unknown and from udp_input() if the local
* port is not bound.
*
* @param p the input packet for which the 'unreachable' should be sent,
* p->payload pointing to the IP header
* @param t type of the 'unreachable' packet
*/
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
MIB2_STATS_INC(mib2.icmpoutdestunreachs);
icmp_send_response(p, ICMP_DUR, t);
}
#if IP_FORWARD || IP_REASSEMBLY
/**
* Send a 'time exceeded' packet, called from ip_forward() if TTL is 0.
*
* @param p the input packet for which the 'time exceeded' should be sent,
* p->payload pointing to the IP header
* @param t type of the 'time exceeded' packet
*/
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{
MIB2_STATS_INC(mib2.icmpouttimeexcds);
icmp_send_response(p, ICMP_TE, t);
}
#endif /* IP_FORWARD || IP_REASSEMBLY */
/**
* Send an icmp packet in response to an incoming packet.
*
* @param p the input packet for which the 'unreachable' should be sent,
* p->payload pointing to the IP header
* @param type Type of the ICMP header
* @param code Code of the ICMP header
*/
static void
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
{
struct pbuf *q;
struct ip_hdr *iphdr;
/* we can use the echo header here */
struct icmp_echo_hdr *icmphdr;
ip4_addr_t iphdr_src;
struct netif *netif;
/* increase number of messages attempted to send */
MIB2_STATS_INC(mib2.icmpoutmsgs);
/* ICMP header + IP header + 8 bytes of data */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
PBUF_RAM);
if (q == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
MIB2_STATS_INC(mib2.icmpouterrors);
return;
}
LWIP_ASSERT("check that first pbuf can hold icmp message",
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
iphdr = (struct ip_hdr *)p->payload;
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src);
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest);
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
icmphdr = (struct icmp_echo_hdr *)q->payload;
icmphdr->type = type;
icmphdr->code = code;
icmphdr->id = 0;
icmphdr->seqno = 0;
/* copy fields from original packet */
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
ip4_addr_copy(iphdr_src, iphdr->src);
#ifdef LWIP_HOOK_IP4_ROUTE_SRC
{
ip4_addr_t iphdr_dst;
ip4_addr_copy(iphdr_dst, iphdr->dest);
netif = ip4_route_src(&iphdr_dst, &iphdr_src);
}
#else
netif = ip4_route(&iphdr_src);
#endif
if (netif != NULL) {
/* calculate checksum */
icmphdr->chksum = 0;
#if CHECKSUM_GEN_ICMP
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {
icmphdr->chksum = inet_chksum(icmphdr, q->len);
}
#endif
ICMP_STATS_INC(icmp.xmit);
ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);
}
pbuf_free(q);
}
#endif /* LWIP_IPV4 && LWIP_ICMP */
@@ -0,0 +1,801 @@
/**
* @file
* IGMP - Internet Group Management Protocol
*
* @defgroup igmp IGMP
* @ingroup ip4
* To be called from TCPIP thread
*/
/*
* Copyright (c) 2002 CITEL Technologies Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is a contribution to the lwIP TCP/IP stack.
* The Swedish Institute of Computer Science and Adam Dunkels
* are specifically granted permission to redistribute this
* source code.
*/
/*-------------------------------------------------------------
Note 1)
Although the rfc requires V1 AND V2 capability
we will only support v2 since now V1 is very old (August 1989)
V1 can be added if required
a debug print and statistic have been implemented to
show this up.
-------------------------------------------------------------
-------------------------------------------------------------
Note 2)
A query for a specific group address (as opposed to ALLHOSTS)
has now been implemented as I am unsure if it is required
a debug print and statistic have been implemented to
show this up.
-------------------------------------------------------------
-------------------------------------------------------------
Note 3)
The router alert rfc 2113 is implemented in outgoing packets
but not checked rigorously incoming
-------------------------------------------------------------
Steve Reynolds
------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
* RFC 988 - Host extensions for IP multicasting - V0
* RFC 1054 - Host extensions for IP multicasting -
* RFC 1112 - Host extensions for IP multicasting - V1
* RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard)
* RFC 3376 - Internet Group Management Protocol, Version 3 - V3
* RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+
* RFC 2113 - IP Router Alert Option -
*----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
* Includes
*----------------------------------------------------------------------------*/
#include "lwip/opt.h"
#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/igmp.h"
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
#include "lwip/prot/igmp.h"
#include <string.h>
static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr);
static err_t igmp_remove_group(struct netif *netif, struct igmp_group *group);
static void igmp_timeout(struct netif *netif, struct igmp_group *group);
static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif);
static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type);
static ip4_addr_t allsystems;
static ip4_addr_t allrouters;
/**
* Initialize the IGMP module
*/
void
igmp_init(void)
{
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n"));
IP4_ADDR(&allsystems, 224, 0, 0, 1);
IP4_ADDR(&allrouters, 224, 0, 0, 2);
}
/**
* Start IGMP processing on interface
*
* @param netif network interface on which start IGMP processing
*/
err_t
igmp_start(struct netif *netif)
{
struct igmp_group *group;
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", (void *)netif));
group = igmp_lookup_group(netif, &allsystems);
if (group != NULL) {
group->group_state = IGMP_GROUP_IDLE_MEMBER;
group->use++;
/* Allow the igmp messages at the MAC level */
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
ip4_addr_debug_print_val(IGMP_DEBUG, allsystems);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void *)netif));
netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER);
}
return ERR_OK;
}
return ERR_MEM;
}
/**
* Stop IGMP processing on interface
*
* @param netif network interface on which stop IGMP processing
*/
err_t
igmp_stop(struct netif *netif)
{
struct igmp_group *group = netif_igmp_data(netif);
netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL);
while (group != NULL) {
struct igmp_group *next = group->next; /* avoid use-after-free below */
/* disable the group at the MAC level */
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
ip4_addr_debug_print_val(IGMP_DEBUG, group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void *)netif));
netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER);
}
/* free group */
memp_free(MEMP_IGMP_GROUP, group);
/* move to "next" */
group = next;
}
return ERR_OK;
}
/**
* Report IGMP memberships for this interface
*
* @param netif network interface on which report IGMP memberships
*/
void
igmp_report_groups(struct netif *netif)
{
struct igmp_group *group = netif_igmp_data(netif);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void *)netif));
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
if (group != NULL) {
group = group->next;
}
while (group != NULL) {
igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
group = group->next;
}
}
/**
* Search for a group in the netif's igmp group list
*
* @param ifp the network interface for which to look
* @param addr the group ip address to search for
* @return a struct igmp_group* if the group has been found,
* NULL if the group wasn't found.
*/
struct igmp_group *
igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr)
{
struct igmp_group *group = netif_igmp_data(ifp);
while (group != NULL) {
if (ip4_addr_cmp(&(group->group_address), addr)) {
return group;
}
group = group->next;
}
/* to be clearer, we return NULL here instead of
* 'group' (which is also NULL at this point).
*/
return NULL;
}
/**
* Search for a specific igmp group and create a new one if not found-
*
* @param ifp the network interface for which to look
* @param addr the group ip address to search
* @return a struct igmp_group*,
* NULL on memory error.
*/
static struct igmp_group *
igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr)
{
struct igmp_group *group;
struct igmp_group *list_head = netif_igmp_data(ifp);
/* Search if the group already exists */
group = igmp_lookfor_group(ifp, addr);
if (group != NULL) {
/* Group already exists. */
return group;
}
/* Group doesn't exist yet, create a new one */
group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
if (group != NULL) {
ip4_addr_set(&(group->group_address), addr);
group->timer = 0; /* Not running */
group->group_state = IGMP_GROUP_NON_MEMBER;
group->last_reporter_flag = 0;
group->use = 0;
/* Ensure allsystems group is always first in list */
if (list_head == NULL) {
/* this is the first entry in linked list */
LWIP_ASSERT("igmp_lookup_group: first group must be allsystems",
(ip4_addr_cmp(addr, &allsystems) != 0));
group->next = NULL;
netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group);
} else {
/* append _after_ first entry */
LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems",
(ip4_addr_cmp(addr, &allsystems) == 0));
group->next = list_head->next;
list_head->next = group;
}
}
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group ? "" : "impossible to ")));
ip4_addr_debug_print(IGMP_DEBUG, addr);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void *)ifp));
return group;
}
/**
* Remove a group from netif's igmp group list, but don't free it yet
*
* @param group the group to remove from the netif's igmp group list
* @return ERR_OK if group was removed from the list, an err_t otherwise
*/
static err_t
igmp_remove_group(struct netif *netif, struct igmp_group *group)
{
err_t err = ERR_OK;
struct igmp_group *tmp_group;
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) {
if (tmp_group->next == group) {
tmp_group->next = group->next;
break;
}
}
/* Group not found in netif's igmp group list */
if (tmp_group == NULL) {
err = ERR_ARG;
}
return err;
}
/**
* Called from ip_input() if a new IGMP packet is received.
*
* @param p received igmp packet, p->payload pointing to the igmp header
* @param inp network interface on which the packet was received
* @param dest destination ip address of the igmp packet
*/
void
igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest)
{
struct igmp_msg *igmp;
struct igmp_group *group;
struct igmp_group *groupref;
IGMP_STATS_INC(igmp.recv);
/* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
if (p->len < IGMP_MINLEN) {
pbuf_free(p);
IGMP_STATS_INC(igmp.lenerr);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));
return;
}
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));
ip4_addr_debug_print_val(IGMP_DEBUG, ip4_current_header()->src);
LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
ip4_addr_debug_print_val(IGMP_DEBUG, ip4_current_header()->dest);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void *)inp));
/* Now calculate and check the checksum */
igmp = (struct igmp_msg *)p->payload;
if (inet_chksum(igmp, p->len)) {
pbuf_free(p);
IGMP_STATS_INC(igmp.chkerr);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n"));
return;
}
/* Packet is ok so find an existing group */
group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */
/* If group can be found or create... */
if (!group) {
pbuf_free(p);
IGMP_STATS_INC(igmp.drop);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n"));
return;
}
/* NOW ACT ON THE INCOMING MESSAGE TYPE... */
switch (igmp->igmp_msgtype) {
case IGMP_MEMB_QUERY:
/* IGMP_MEMB_QUERY to the "all systems" address ? */
if ((ip4_addr_cmp(dest, &allsystems)) && ip4_addr_isany(&igmp->igmp_group_address)) {
/* THIS IS THE GENERAL QUERY */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
if (igmp->igmp_maxresp == 0) {
IGMP_STATS_INC(igmp.rx_v1);
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
} else {
IGMP_STATS_INC(igmp.rx_general);
}
groupref = netif_igmp_data(inp);
/* Do not send messages on the all systems group address! */
/* Skip the first group in the list, it is always the allsystems group added in igmp_start() */
if (groupref != NULL) {
groupref = groupref->next;
}
while (groupref) {
igmp_delaying_member(groupref, igmp->igmp_maxresp);
groupref = groupref->next;
}
} else {
/* IGMP_MEMB_QUERY to a specific group ? */
if (!ip4_addr_isany(&igmp->igmp_group_address)) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
ip4_addr_debug_print_val(IGMP_DEBUG, igmp->igmp_group_address);
if (ip4_addr_cmp(dest, &allsystems)) {
ip4_addr_t groupaddr;
LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
/* we first need to re-look for the group since we used dest last time */
ip4_addr_copy(groupaddr, igmp->igmp_group_address);
group = igmp_lookfor_group(inp, &groupaddr);
} else {
LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
}
if (group != NULL) {
IGMP_STATS_INC(igmp.rx_group);
igmp_delaying_member(group, igmp->igmp_maxresp);
} else {
IGMP_STATS_INC(igmp.drop);
}
} else {
IGMP_STATS_INC(igmp.proterr);
}
}
break;
case IGMP_V2_MEMB_REPORT:
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));
IGMP_STATS_INC(igmp.rx_report);
if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
/* This is on a specific group we have already looked up */
group->timer = 0; /* stopped */
group->group_state = IGMP_GROUP_IDLE_MEMBER;
group->last_reporter_flag = 0;
}
break;
default:
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
igmp->igmp_msgtype, group->group_state, (void *)&group, (void *)inp));
IGMP_STATS_INC(igmp.proterr);
break;
}
pbuf_free(p);
return;
}
/**
* @ingroup igmp
* Join a group on one network interface.
*
* @param ifaddr ip address of the network interface which should join a new group
* @param groupaddr the ip address of the group which to join
* @return ERR_OK if group was joined on the netif(s), an err_t otherwise
*/
err_t
igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
{
err_t err = ERR_VAL; /* no matching interface */
struct netif *netif;
LWIP_ASSERT_CORE_LOCKED();
/* make sure it is multicast address */
LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
/* loop through netif's */
NETIF_FOREACH(netif) {
/* Should we join this interface ? */
if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
err = igmp_joingroup_netif(netif, groupaddr);
if (err != ERR_OK) {
/* Return an error even if some network interfaces are joined */
/** @todo undo any other netif already joined */
return err;
}
}
}
return err;
}
/**
* @ingroup igmp
* Join a group on one network interface.
*
* @param netif the network interface which should join a new group
* @param groupaddr the ip address of the group which to join
* @return ERR_OK if group was joined on the netif, an err_t otherwise
*/
err_t
igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
{
struct igmp_group *group;
LWIP_ASSERT_CORE_LOCKED();
/* make sure it is multicast address */
LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
/* make sure it is an igmp-enabled netif */
LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
/* find group or create a new one if not found */
group = igmp_lookup_group(netif, groupaddr);
if (group != NULL) {
/* This should create a new group, check the state to make sure */
if (group->group_state != IGMP_GROUP_NON_MEMBER) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n"));
} else {
/* OK - it was new group */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
/* If first use of the group, allow the group at the MAC level */
if ((group->use == 0) && (netif->igmp_mac_filter != NULL)) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void *)netif));
netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER);
}
IGMP_STATS_INC(igmp.tx_join);
igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
/* Need to work out where this timer comes from */
group->group_state = IGMP_GROUP_DELAYING_MEMBER;
}
/* Increment group use */
group->use++;
/* Join on this interface */
return ERR_OK;
} else {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n"));
return ERR_MEM;
}
}
/**
* @ingroup igmp
* Leave a group on one network interface.
*
* @param ifaddr ip address of the network interface which should leave a group
* @param groupaddr the ip address of the group which to leave
* @return ERR_OK if group was left on the netif(s), an err_t otherwise
*/
err_t
igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
{
err_t err = ERR_VAL; /* no matching interface */
struct netif *netif;
LWIP_ASSERT_CORE_LOCKED();
/* make sure it is multicast address */
LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
/* loop through netif's */
NETIF_FOREACH(netif) {
/* Should we leave this interface ? */
if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
err_t res = igmp_leavegroup_netif(netif, groupaddr);
if (err != ERR_OK) {
/* Store this result if we have not yet gotten a success */
err = res;
}
}
}
return err;
}
/**
* @ingroup igmp
* Leave a group on one network interface.
*
* @param netif the network interface which should leave a group
* @param groupaddr the ip address of the group which to leave
* @return ERR_OK if group was left on the netif, an err_t otherwise
*/
err_t
igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
{
struct igmp_group *group;
LWIP_ASSERT_CORE_LOCKED();
/* make sure it is multicast address */
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
/* make sure it is an igmp-enabled netif */
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
/* find group */
group = igmp_lookfor_group(netif, groupaddr);
if (group != NULL) {
/* Only send a leave if the flag is set according to the state diagram */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
/* If there is no other use of the group */
if (group->use <= 1) {
/* Remove the group from the list */
igmp_remove_group(netif, group);
/* If we are the last reporter for this group */
if (group->last_reporter_flag) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n"));
IGMP_STATS_INC(igmp.tx_leave);
igmp_send(netif, group, IGMP_LEAVE_GROUP);
}
/* Disable the group at the MAC level */
if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void *)netif));
netif->igmp_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER);
}
/* Free group struct */
memp_free(MEMP_IGMP_GROUP, group);
} else {
/* Decrement group use */
group->use--;
}
return ERR_OK;
} else {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n"));
return ERR_VAL;
}
}
/**
* The igmp timer function (both for NO_SYS=1 and =0)
* Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default).
*/
void
igmp_tmr(void)
{
struct netif *netif;
NETIF_FOREACH(netif) {
struct igmp_group *group = netif_igmp_data(netif);
while (group != NULL) {
if (group->timer > 0) {
group->timer--;
if (group->timer == 0) {
igmp_timeout(netif, group);
}
}
group = group->next;
}
}
}
/**
* Called if a timeout for one group is reached.
* Sends a report for this group.
*
* @param group an igmp_group for which a timeout is reached
*/
static void
igmp_timeout(struct netif *netif, struct igmp_group *group)
{
/* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group
(unless it is the allsystems group) */
if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
(!(ip4_addr_cmp(&(group->group_address), &allsystems)))) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
ip4_addr_debug_print_val(IGMP_DEBUG, group->group_address);
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void *)netif));
group->group_state = IGMP_GROUP_IDLE_MEMBER;
IGMP_STATS_INC(igmp.tx_report);
igmp_send(netif, group, IGMP_V2_MEMB_REPORT);
}
}
/**
* Start a timer for an igmp group
*
* @param group the igmp_group for which to start a timer
* @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with
* every call to igmp_tmr())
*/
static void
igmp_start_timer(struct igmp_group *group, u8_t max_time)
{
#ifdef LWIP_RAND
group->timer = (u16_t)(max_time > 2 ? (LWIP_RAND() % max_time) : 1);
#else /* LWIP_RAND */
/* ATTENTION: use this only if absolutely necessary! */
group->timer = max_time / 2;
#endif /* LWIP_RAND */
if (group->timer == 0) {
group->timer = 1;
}
}
/**
* Delaying membership report for a group if necessary
*
* @param group the igmp_group for which "delaying" membership report
* @param maxresp query delay
*/
static void
igmp_delaying_member(struct igmp_group *group, u8_t maxresp)
{
if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
((group->timer == 0) || (maxresp < group->timer)))) {
igmp_start_timer(group, maxresp);
group->group_state = IGMP_GROUP_DELAYING_MEMBER;
}
}
/**
* Sends an IP packet on a network interface. This function constructs the IP header
* and calculates the IP header checksum. If the source IP address is NULL,
* the IP address of the outgoing network interface is filled in as source address.
*
* @param p the packet to send (p->payload points to the data, e.g. next
protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
IP header and p->payload points to that IP header)
* @param src the source IP address to send from (if src == IP4_ADDR_ANY, the
* IP address of the netif used to send is used as source address)
* @param dest the destination IP address to send the packet to
* @param netif the netif on which to send this packet
* @return ERR_OK if the packet was sent OK
* ERR_BUF if p doesn't have enough space for IP/LINK headers
* returns errors returned by netif->output
*/
static err_t
igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif)
{
/* This is the "router alert" option */
u16_t ra[2];
ra[0] = PP_HTONS(ROUTER_ALERT);
ra[1] = 0x0000; /* Router shall examine packet */
IGMP_STATS_INC(igmp.xmit);
return ip4_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
}
/**
* Send an igmp packet to a specific group.
*
* @param group the group to which to send the packet
* @param type the type of igmp packet to send
*/
static void
igmp_send(struct netif *netif, struct igmp_group *group, u8_t type)
{
struct pbuf *p = NULL;
struct igmp_msg *igmp = NULL;
ip4_addr_t src = *IP4_ADDR_ANY4;
ip4_addr_t *dest = NULL;
/* IP header + "router alert" option + IGMP header */
p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);
if (p) {
igmp = (struct igmp_msg *)p->payload;
LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
(p->len >= sizeof(struct igmp_msg)));
ip4_addr_copy(src, *netif_ip4_addr(netif));
if (type == IGMP_V2_MEMB_REPORT) {
dest = &(group->group_address);
ip4_addr_copy(igmp->igmp_group_address, group->group_address);
group->last_reporter_flag = 1; /* Remember we were the last to report */
} else {
if (type == IGMP_LEAVE_GROUP) {
dest = &allrouters;
ip4_addr_copy(igmp->igmp_group_address, group->group_address);
}
}
if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) {
igmp->igmp_msgtype = type;
igmp->igmp_maxresp = 0;
igmp->igmp_checksum = 0;
igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN);
igmp_ip_output_if(p, &src, dest, netif);
}
pbuf_free(p);
} else {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
IGMP_STATS_INC(igmp.memerr);
}
}
#endif /* LWIP_IPV4 && LWIP_IGMP */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,321 @@
/**
* @file
* This is the IPv4 address tools implementation.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if LWIP_IPV4
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST);
/**
* Determine if an address is a broadcast address on a network interface
*
* @param addr address to be checked
* @param netif the network interface against which the address is checked
* @return returns non-zero if the address is a broadcast address
*/
u8_t
ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif)
{
ip4_addr_t ipaddr;
ip4_addr_set_u32(&ipaddr, addr);
/* all ones (broadcast) or all zeroes (old skool broadcast) */
if ((~addr == IPADDR_ANY) ||
(addr == IPADDR_ANY)) {
return 1;
/* no broadcast support on this network interface? */
} else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
/* the given address cannot be a broadcast address
* nor can we check against any broadcast addresses */
return 0;
/* address matches network interface address exactly? => no broadcast */
} else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) {
return 0;
/* on the same (sub) network... */
} else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif))
/* ...and host identifier bits are all ones? =>... */
&& ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) ==
(IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) {
/* => network broadcast address */
return 1;
} else {
return 0;
}
}
/** Checks if a netmask is valid (starting with ones, then only zeros)
*
* @param netmask the IPv4 netmask to check (in network byte order!)
* @return 1 if the netmask is valid, 0 if it is not
*/
u8_t
ip4_addr_netmask_valid(u32_t netmask)
{
u32_t mask;
u32_t nm_hostorder = lwip_htonl(netmask);
/* first, check for the first zero */
for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
if ((nm_hostorder & mask) == 0) {
break;
}
}
/* then check that there is no one */
for (; mask != 0; mask >>= 1) {
if ((nm_hostorder & mask) != 0) {
/* there is a one after the first zero -> invalid */
return 0;
}
}
/* no one after the first zero -> valid */
return 1;
}
/**
* Ascii internet address interpretation routine.
* The value returned is in network order.
*
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
* @return ip address in network order
*/
u32_t
ipaddr_addr(const char *cp)
{
ip4_addr_t val;
if (ip4addr_aton(cp, &val)) {
return ip4_addr_get_u32(&val);
}
return (IPADDR_NONE);
}
/**
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
* This replaces inet_addr, the return value from which
* cannot distinguish between failure and a local broadcast address.
*
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
* @param addr pointer to which to save the ip address in network order
* @return 1 if cp could be converted to addr, 0 on failure
*/
int
ip4addr_aton(const char *cp, ip4_addr_t *addr)
{
u32_t val;
u8_t base;
char c;
u32_t parts[4];
u32_t *pp = parts;
c = *cp;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, 1-9=decimal.
*/
if (!lwip_isdigit(c)) {
return 0;
}
val = 0;
base = 10;
if (c == '0') {
c = *++cp;
if (c == 'x' || c == 'X') {
base = 16;
c = *++cp;
} else {
base = 8;
}
}
for (;;) {
if (lwip_isdigit(c)) {
val = (val * base) + (u32_t)(c - '0');
c = *++cp;
} else if (base == 16 && lwip_isxdigit(c)) {
val = (val << 4) | (u32_t)(c + 10 - (lwip_islower(c) ? 'a' : 'A'));
c = *++cp;
} else {
break;
}
}
if (c == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3) {
return 0;
}
*pp++ = val;
c = *++cp;
} else {
break;
}
}
/*
* Check for trailing characters.
*/
if (c != '\0' && !lwip_isspace(c)) {
return 0;
}
/*
* Concoct the address according to
* the number of parts specified.
*/
switch (pp - parts + 1) {
case 0:
return 0; /* initial nondigit */
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffffUL) {
return 0;
}
if (parts[0] > 0xff) {
return 0;
}
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff) {
return 0;
}
if ((parts[0] > 0xff) || (parts[1] > 0xff)) {
return 0;
}
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff) {
return 0;
}
if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) {
return 0;
}
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
default:
LWIP_ASSERT("unhandled", 0);
break;
}
if (addr) {
ip4_addr_set_u32(addr, lwip_htonl(val));
}
return 1;
}
/**
* Convert numeric IP address into decimal dotted ASCII representation.
* returns ptr to static buffer; not reentrant!
*
* @param addr ip address in network order to convert
* @return pointer to a global static (!) buffer that holds the ASCII
* representation of addr
*/
char *
ip4addr_ntoa(const ip4_addr_t *addr)
{
static char str[IP4ADDR_STRLEN_MAX];
return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
}
/**
* Same as ip4addr_ntoa, but reentrant since a user-supplied buffer is used.
*
* @param addr ip address in network order to convert
* @param buf target buffer where the string is stored
* @param buflen length of buf
* @return either pointer to buf which now holds the ASCII
* representation of addr or NULL if buf was too small
*/
char *
ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
{
u32_t s_addr;
char inv[3];
char *rp;
u8_t *ap;
u8_t rem;
u8_t n;
u8_t i;
int len = 0;
s_addr = ip4_addr_get_u32(addr);
rp = buf;
ap = (u8_t *)&s_addr;
for (n = 0; n < 4; n++) {
i = 0;
do {
rem = *ap % (u8_t)10;
*ap /= (u8_t)10;
inv[i++] = (char)('0' + rem);
} while (*ap);
while (i--) {
if (len++ >= buflen) {
return NULL;
}
*rp++ = inv[i];
}
if (len++ >= buflen) {
return NULL;
}
*rp++ = '.';
ap++;
}
*--rp = 0;
return buf;
}
#endif /* LWIP_IPV4 */
@@ -0,0 +1,894 @@
/**
* @file
* This is the IPv4 packet segmentation and reassembly implementation.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Jani Monoses <jani@iv.ro>
* Simon Goldschmidt
* original reassembly code by Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if LWIP_IPV4
#include "lwip/ip4_frag.h"
#include "lwip/def.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
#include "lwip/icmp.h"
#include <string.h>
#if IP_REASSEMBLY
/**
* The IP reassembly code currently has the following limitations:
* - IP header options are not supported
* - fragments must not overlap (e.g. due to different routes),
* currently, overlapping or duplicate fragments are thrown away
* if IP_REASS_CHECK_OVERLAP=1 (the default)!
*
* @todo: work with IP header options
*/
/** Setting this to 0, you can turn off checking the fragments for overlapping
* regions. The code gets a little smaller. Only use this if you know that
* overlapping won't occur on your network! */
#ifndef IP_REASS_CHECK_OVERLAP
#define IP_REASS_CHECK_OVERLAP 1
#endif /* IP_REASS_CHECK_OVERLAP */
/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is
* full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller.
* Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA
* is set to 1, so one datagram can be reassembled at a time, only. */
#ifndef IP_REASS_FREE_OLDEST
#define IP_REASS_FREE_OLDEST 1
#endif /* IP_REASS_FREE_OLDEST */
#define IP_REASS_FLAG_LASTFRAG 0x01
#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1
#define IP_REASS_VALIDATE_PBUF_QUEUED 0
#define IP_REASS_VALIDATE_PBUF_DROPPED -1
/** This is a helper struct which holds the starting
* offset and the ending offset of this fragment to
* easily chain the fragments.
* It has the same packing requirements as the IP header, since it replaces
* the IP header in memory in incoming fragments (after copying it) to keep
* track of the various fragments. (-> If the IP header doesn't need packing,
* this struct doesn't need packing, too.)
*/
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_reass_helper {
PACK_STRUCT_FIELD(struct pbuf *next_pbuf);
PACK_STRUCT_FIELD(u16_t start);
PACK_STRUCT_FIELD(u16_t end);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \
(ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \
ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \
IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0
/* global variables */
static struct ip_reassdata *reassdatagrams;
static u16_t ip_reass_pbufcount;
/* function prototypes */
static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev);
static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev);
/**
* Reassembly timer base function
* for both NO_SYS == 0 and 1 (!).
*
* Should be called every 1000 msec (defined by IP_TMR_INTERVAL).
*/
void
ip_reass_tmr(void)
{
struct ip_reassdata *r, *prev = NULL;
r = reassdatagrams;
while (r != NULL) {
/* Decrement the timer. Once it reaches 0,
* clean up the incomplete fragment assembly */
if (r->timer > 0) {
r->timer--;
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n", (u16_t)r->timer));
prev = r;
r = r->next;
} else {
/* reassembly timed out */
struct ip_reassdata *tmp;
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n"));
tmp = r;
/* get the next pointer before freeing */
r = r->next;
/* free the helper struct and all enqueued pbufs */
ip_reass_free_complete_datagram(tmp, prev);
}
}
}
/**
* Free a datagram (struct ip_reassdata) and all its pbufs.
* Updates the total count of enqueued pbufs (ip_reass_pbufcount),
* SNMP counters and sends an ICMP time exceeded packet.
*
* @param ipr datagram to free
* @param prev the previous datagram in the linked list
* @return the number of pbufs freed
*/
static int
ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
{
u16_t pbufs_freed = 0;
u16_t clen;
struct pbuf *p;
struct ip_reass_helper *iprh;
LWIP_ASSERT("prev != ipr", prev != ipr);
if (prev != NULL) {
LWIP_ASSERT("prev->next == ipr", prev->next == ipr);
}
MIB2_STATS_INC(mib2.ipreasmfails);
#if LWIP_ICMP
iprh = (struct ip_reass_helper *)ipr->p->payload;
if (iprh->start == 0) {
/* The first fragment was received, send ICMP time exceeded. */
/* First, de-queue the first pbuf from r->p. */
p = ipr->p;
ipr->p = iprh->next_pbuf;
/* Then, copy the original header into it. */
SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
icmp_time_exceeded(p, ICMP_TE_FRAG);
clen = pbuf_clen(p);
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
pbufs_freed = (u16_t)(pbufs_freed + clen);
pbuf_free(p);
}
#endif /* LWIP_ICMP */
/* First, free all received pbufs. The individual pbufs need to be released
separately as they have not yet been chained */
p = ipr->p;
while (p != NULL) {
struct pbuf *pcur;
iprh = (struct ip_reass_helper *)p->payload;
pcur = p;
/* get the next pointer before freeing */
p = iprh->next_pbuf;
clen = pbuf_clen(pcur);
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
pbufs_freed = (u16_t)(pbufs_freed + clen);
pbuf_free(pcur);
}
/* Then, unchain the struct ip_reassdata from the list and free it. */
ip_reass_dequeue_datagram(ipr, prev);
LWIP_ASSERT("ip_reass_pbufcount >= pbufs_freed", ip_reass_pbufcount >= pbufs_freed);
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount - pbufs_freed);
return pbufs_freed;
}
#if IP_REASS_FREE_OLDEST
/**
* Free the oldest datagram to make room for enqueueing new fragments.
* The datagram 'fraghdr' belongs to is not freed!
*
* @param fraghdr IP header of the current fragment
* @param pbufs_needed number of pbufs needed to enqueue
* (used for freeing other datagrams if not enough space)
* @return the number of pbufs freed
*/
static int
ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
{
/* @todo Can't we simply remove the last datagram in the
* linked list behind reassdatagrams?
*/
struct ip_reassdata *r, *oldest, *prev, *oldest_prev;
int pbufs_freed = 0, pbufs_freed_current;
int other_datagrams;
/* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
* but don't free the datagram that 'fraghdr' belongs to! */
do {
oldest = NULL;
prev = NULL;
oldest_prev = NULL;
other_datagrams = 0;
r = reassdatagrams;
while (r != NULL) {
if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) {
/* Not the same datagram as fraghdr */
other_datagrams++;
if (oldest == NULL) {
oldest = r;
oldest_prev = prev;
} else if (r->timer <= oldest->timer) {
/* older than the previous oldest */
oldest = r;
oldest_prev = prev;
}
}
if (r->next != NULL) {
prev = r;
}
r = r->next;
}
if (oldest != NULL) {
pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev);
pbufs_freed += pbufs_freed_current;
}
} while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1));
return pbufs_freed;
}
#endif /* IP_REASS_FREE_OLDEST */
/**
* Enqueues a new fragment into the fragment queue
* @param fraghdr points to the new fragments IP hdr
* @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space)
* @return A pointer to the queue location into which the fragment was enqueued
*/
static struct ip_reassdata *
ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen)
{
struct ip_reassdata *ipr;
#if ! IP_REASS_FREE_OLDEST
LWIP_UNUSED_ARG(clen);
#endif
/* No matching previous fragment found, allocate a new reassdata struct */
ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
if (ipr == NULL) {
#if IP_REASS_FREE_OLDEST
if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
}
if (ipr == NULL)
#endif /* IP_REASS_FREE_OLDEST */
{
IPFRAG_STATS_INC(ip_frag.memerr);
LWIP_DEBUGF(IP_REASS_DEBUG, ("Failed to alloc reassdata struct\n"));
return NULL;
}
}
memset(ipr, 0, sizeof(struct ip_reassdata));
ipr->timer = IP_REASS_MAXAGE;
/* enqueue the new structure to the front of the list */
ipr->next = reassdatagrams;
reassdatagrams = ipr;
/* copy the ip header for later tests and input */
/* @todo: no ip options supported? */
SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN);
return ipr;
}
/**
* Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs.
* @param ipr points to the queue entry to dequeue
*/
static void
ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
{
/* dequeue the reass struct */
if (reassdatagrams == ipr) {
/* it was the first in the list */
reassdatagrams = ipr->next;
} else {
/* it wasn't the first, so it must have a valid 'prev' */
LWIP_ASSERT("sanity check linked list", prev != NULL);
prev->next = ipr->next;
}
/* now we can free the ip_reassdata struct */
memp_free(MEMP_REASSDATA, ipr);
}
/**
* Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list
* will grow over time as new pbufs are rx.
* Also checks that the datagram passes basic continuity checks (if the last
* fragment was received at least once).
* @param ipr points to the reassembly state
* @param new_p points to the pbuf for the current fragment
* @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet)
* @return see IP_REASS_VALIDATE_* defines
*/
static int
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last)
{
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev = NULL;
struct pbuf *q;
u16_t offset, len;
u8_t hlen;
struct ip_hdr *fraghdr;
int valid = 1;
/* Extract length and fragment offset from current fragment */
fraghdr = (struct ip_hdr *)new_p->payload;
len = lwip_ntohs(IPH_LEN(fraghdr));
hlen = IPH_HL_BYTES(fraghdr);
if (hlen > len) {
/* invalid datagram */
return IP_REASS_VALIDATE_PBUF_DROPPED;
}
len = (u16_t)(len - hlen);
offset = IPH_OFFSET_BYTES(fraghdr);
/* overwrite the fragment's ip header from the pbuf with our helper struct,
* and setup the embedded helper structure. */
/* make sure the struct ip_reass_helper fits into the IP header */
LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN",
sizeof(struct ip_reass_helper) <= IP_HLEN);
iprh = (struct ip_reass_helper *)new_p->payload;
iprh->next_pbuf = NULL;
iprh->start = offset;
iprh->end = (u16_t)(offset + len);
if (iprh->end < offset) {
/* u16_t overflow, cannot handle this */
return IP_REASS_VALIDATE_PBUF_DROPPED;
}
/* Iterate through until we either get to the end of the list (append),
* or we find one with a larger offset (insert). */
for (q = ipr->p; q != NULL;) {
iprh_tmp = (struct ip_reass_helper *)q->payload;
if (iprh->start < iprh_tmp->start) {
/* the new pbuf should be inserted before this */
iprh->next_pbuf = q;
if (iprh_prev != NULL) {
/* not the fragment with the lowest offset */
#if IP_REASS_CHECK_OVERLAP
if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
/* fragment overlaps with previous or following, throw away */
return IP_REASS_VALIDATE_PBUF_DROPPED;
}
#endif /* IP_REASS_CHECK_OVERLAP */
iprh_prev->next_pbuf = new_p;
if (iprh_prev->end != iprh->start) {
/* There is a fragment missing between the current
* and the previous fragment */
valid = 0;
}
} else {
#if IP_REASS_CHECK_OVERLAP
if (iprh->end > iprh_tmp->start) {
/* fragment overlaps with following, throw away */
return IP_REASS_VALIDATE_PBUF_DROPPED;
}
#endif /* IP_REASS_CHECK_OVERLAP */
/* fragment with the lowest offset */
ipr->p = new_p;
}
break;
} else if (iprh->start == iprh_tmp->start) {
/* received the same datagram twice: no need to keep the datagram */
return IP_REASS_VALIDATE_PBUF_DROPPED;
#if IP_REASS_CHECK_OVERLAP
} else if (iprh->start < iprh_tmp->end) {
/* overlap: no need to keep the new datagram */
return IP_REASS_VALIDATE_PBUF_DROPPED;
#endif /* IP_REASS_CHECK_OVERLAP */
} else {
/* Check if the fragments received so far have no holes. */
if (iprh_prev != NULL) {
if (iprh_prev->end != iprh_tmp->start) {
/* There is a fragment missing between the current
* and the previous fragment */
valid = 0;
}
}
}
q = iprh_tmp->next_pbuf;
iprh_prev = iprh_tmp;
}
/* If q is NULL, then we made it to the end of the list. Determine what to do now */
if (q == NULL) {
if (iprh_prev != NULL) {
/* this is (for now), the fragment with the highest offset:
* chain it to the last fragment */
#if IP_REASS_CHECK_OVERLAP
LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start);
#endif /* IP_REASS_CHECK_OVERLAP */
iprh_prev->next_pbuf = new_p;
if (iprh_prev->end != iprh->start) {
valid = 0;
}
} else {
#if IP_REASS_CHECK_OVERLAP
LWIP_ASSERT("no previous fragment, this must be the first fragment!",
ipr->p == NULL);
#endif /* IP_REASS_CHECK_OVERLAP */
/* this is the first fragment we ever received for this ip datagram */
ipr->p = new_p;
}
}
/* At this point, the validation part begins: */
/* If we already received the last fragment */
if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) {
/* and had no holes so far */
if (valid) {
/* then check if the rest of the fragments is here */
/* Check if the queue starts with the first datagram */
if ((ipr->p == NULL) || (((struct ip_reass_helper *)ipr->p->payload)->start != 0)) {
valid = 0;
} else {
/* and check that there are no holes after this datagram */
iprh_prev = iprh;
q = iprh->next_pbuf;
while (q != NULL) {
iprh = (struct ip_reass_helper *)q->payload;
if (iprh_prev->end != iprh->start) {
valid = 0;
break;
}
iprh_prev = iprh;
q = iprh->next_pbuf;
}
/* if still valid, all fragments are received
* (because to the MF==0 already arrived */
if (valid) {
LWIP_ASSERT("sanity check", ipr->p != NULL);
LWIP_ASSERT("sanity check",
((struct ip_reass_helper *)ipr->p->payload) != iprh);
LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
iprh->next_pbuf == NULL);
}
}
}
/* If valid is 0 here, there are some fragments missing in the middle
* (since MF == 0 has already arrived). Such datagrams simply time out if
* no more fragments are received... */
return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
}
/* If we come here, not all fragments were received, yet! */
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
}
/**
* Reassembles incoming IP fragments into an IP datagram.
*
* @param p points to a pbuf chain of the fragment
* @return NULL if reassembly is incomplete, ? otherwise
*/
struct pbuf *
ip4_reass(struct pbuf *p)
{
struct pbuf *r;
struct ip_hdr *fraghdr;
struct ip_reassdata *ipr;
struct ip_reass_helper *iprh;
u16_t offset, len, clen;
u8_t hlen;
int valid;
int is_last;
IPFRAG_STATS_INC(ip_frag.recv);
MIB2_STATS_INC(mib2.ipreasmreqds);
fraghdr = (struct ip_hdr *)p->payload;
if (IPH_HL_BYTES(fraghdr) != IP_HLEN) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: IP options currently not supported!\n"));
IPFRAG_STATS_INC(ip_frag.err);
goto nullreturn;
}
offset = IPH_OFFSET_BYTES(fraghdr);
len = lwip_ntohs(IPH_LEN(fraghdr));
hlen = IPH_HL_BYTES(fraghdr);
if (hlen > len) {
/* invalid datagram */
goto nullreturn;
}
len = (u16_t)(len - hlen);
/* Check if we are allowed to enqueue more datagrams. */
clen = pbuf_clen(p);
if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {
#if IP_REASS_FREE_OLDEST
if (!ip_reass_remove_oldest_datagram(fraghdr, clen) ||
((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS))
#endif /* IP_REASS_FREE_OLDEST */
{
/* No datagram could be freed and still too many pbufs enqueued */
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n",
ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS));
IPFRAG_STATS_INC(ip_frag.memerr);
/* @todo: send ICMP time exceeded here? */
/* drop this pbuf */
goto nullreturn;
}
}
/* Look for the datagram the fragment belongs to in the current datagram queue,
* remembering the previous in the queue for later dequeueing. */
for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) {
/* Check if the incoming fragment matches the one currently present
in the reassembly buffer. If so, we proceed with copying the
fragment into the buffer. */
if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n",
lwip_ntohs(IPH_ID(fraghdr))));
IPFRAG_STATS_INC(ip_frag.cachehit);
break;
}
}
if (ipr == NULL) {
/* Enqueue a new datagram into the datagram queue */
ipr = ip_reass_enqueue_new_datagram(fraghdr, clen);
/* Bail if unable to enqueue */
if (ipr == NULL) {
goto nullreturn;
}
} else {
if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) &&
((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) {
/* ipr->iphdr is not the header from the first fragment, but fraghdr is
* -> copy fraghdr into ipr->iphdr since we want to have the header
* of the first fragment (for ICMP time exceeded and later, for copying
* all options, if supported)*/
SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
}
}
/* At this point, we have either created a new entry or pointing
* to an existing one */
/* check for 'no more fragments', and update queue entry*/
is_last = (IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0;
if (is_last) {
u16_t datagram_len = (u16_t)(offset + len);
if ((datagram_len < offset) || (datagram_len > (0xFFFF - IP_HLEN))) {
/* u16_t overflow, cannot handle this */
goto nullreturn_ipr;
}
}
/* find the right place to insert this pbuf */
/* @todo: trim pbufs if fragments are overlapping */
valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last);
if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) {
goto nullreturn_ipr;
}
/* if we come here, the pbuf has been enqueued */
/* Track the current number of pbufs current 'in-flight', in order to limit
the number of fragments that may be enqueued at any one time
(overflow checked by testing against IP_REASS_MAX_PBUFS) */
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen);
if (is_last) {
u16_t datagram_len = (u16_t)(offset + len);
ipr->datagram_len = datagram_len;
ipr->flags |= IP_REASS_FLAG_LASTFRAG;
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip4_reass: last fragment seen, total len %"S16_F"\n",
ipr->datagram_len));
}
if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) {
struct ip_reassdata *ipr_prev;
/* the totally last fragment (flag more fragments = 0) was received at least
* once AND all fragments are received */
u16_t datagram_len = (u16_t)(ipr->datagram_len + IP_HLEN);
/* save the second pbuf before copying the header over the pointer */
r = ((struct ip_reass_helper *)ipr->p->payload)->next_pbuf;
/* copy the original ip header back to the first pbuf */
fraghdr = (struct ip_hdr *)(ipr->p->payload);
SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN);
IPH_LEN_SET(fraghdr, lwip_htons(datagram_len));
IPH_OFFSET_SET(fraghdr, 0);
IPH_CHKSUM_SET(fraghdr, 0);
/* @todo: do we need to set/calculate the correct checksum? */
#if CHECKSUM_GEN_IP
IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) {
IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN));
}
#endif /* CHECKSUM_GEN_IP */
p = ipr->p;
/* chain together the pbufs contained within the reass_data list. */
while (r != NULL) {
iprh = (struct ip_reass_helper *)r->payload;
/* hide the ip header for every succeeding fragment */
pbuf_remove_header(r, IP_HLEN);
pbuf_cat(p, r);
r = iprh->next_pbuf;
}
/* find the previous entry in the linked list */
if (ipr == reassdatagrams) {
ipr_prev = NULL;
} else {
for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) {
if (ipr_prev->next == ipr) {
break;
}
}
}
/* release the sources allocate for the fragment queue entry */
ip_reass_dequeue_datagram(ipr, ipr_prev);
/* and adjust the number of pbufs currently queued for reassembly. */
clen = pbuf_clen(p);
LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= clen);
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount - clen);
MIB2_STATS_INC(mib2.ipreasmoks);
/* Return the pbuf chain */
return p;
}
/* the datagram is not (yet?) reassembled completely */
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount));
return NULL;
nullreturn_ipr:
LWIP_ASSERT("ipr != NULL", ipr != NULL);
if (ipr->p == NULL) {
/* dropped pbuf after creating a new datagram entry: remove the entry, too */
LWIP_ASSERT("not firstalthough just enqueued", ipr == reassdatagrams);
ip_reass_dequeue_datagram(ipr, NULL);
}
nullreturn:
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: nullreturn\n"));
IPFRAG_STATS_INC(ip_frag.drop);
pbuf_free(p);
return NULL;
}
#endif /* IP_REASSEMBLY */
#if IP_FRAG
#if !LWIP_NETIF_TX_SINGLE_PBUF
/** Allocate a new struct pbuf_custom_ref */
static struct pbuf_custom_ref *
ip_frag_alloc_pbuf_custom_ref(void)
{
return (struct pbuf_custom_ref *)memp_malloc(MEMP_FRAG_PBUF);
}
/** Free a struct pbuf_custom_ref */
static void
ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref *p)
{
LWIP_ASSERT("p != NULL", p != NULL);
memp_free(MEMP_FRAG_PBUF, p);
}
/** Free-callback function to free a 'struct pbuf_custom_ref', called by
* pbuf_free. */
static void
ipfrag_free_pbuf_custom(struct pbuf *p)
{
struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref *)p;
LWIP_ASSERT("pcr != NULL", pcr != NULL);
LWIP_ASSERT("pcr == p", (void *)pcr == (void *)p);
if (pcr->original != NULL) {
pbuf_free(pcr->original);
}
ip_frag_free_pbuf_custom_ref(pcr);
}
#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
/**
* Fragment an IP datagram if too large for the netif.
*
* Chop the datagram in MTU sized chunks and send them in order
* by pointing PBUF_REFs into p.
*
* @param p ip packet to send
* @param netif the netif on which to send
* @param dest destination ip address to which to send
*
* @return ERR_OK if sent successfully, err_t otherwise
*/
err_t
ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
{
struct pbuf *rambuf;
#if !LWIP_NETIF_TX_SINGLE_PBUF
struct pbuf *newpbuf;
u16_t newpbuflen = 0;
u16_t left_to_copy;
#endif
struct ip_hdr *original_iphdr;
struct ip_hdr *iphdr;
const u16_t nfb = (u16_t)((netif->mtu - IP_HLEN) / 8);
u16_t left, fragsize;
u16_t ofo;
int last;
u16_t poff = IP_HLEN;
u16_t tmp;
int mf_set;
original_iphdr = (struct ip_hdr *)p->payload;
iphdr = original_iphdr;
if (IPH_HL_BYTES(iphdr) != IP_HLEN) {
/* ip4_frag() does not support IP options */
return ERR_VAL;
}
LWIP_ERROR("ip4_frag(): pbuf too short", p->len >= IP_HLEN, return ERR_VAL);
/* Save original offset */
tmp = lwip_ntohs(IPH_OFFSET(iphdr));
ofo = tmp & IP_OFFMASK;
/* already fragmented? if so, the last fragment we create must have MF, too */
mf_set = tmp & IP_MF;
left = (u16_t)(p->tot_len - IP_HLEN);
while (left) {
/* Fill this fragment */
fragsize = LWIP_MIN(left, (u16_t)(nfb * 8));
#if LWIP_NETIF_TX_SINGLE_PBUF
rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM);
if (rambuf == NULL) {
goto memerr;
}
LWIP_ASSERT("this needs a pbuf in one piece!",
(rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff);
/* make room for the IP header */
if (pbuf_add_header(rambuf, IP_HLEN)) {
pbuf_free(rambuf);
goto memerr;
}
/* fill in the IP header */
SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
iphdr = (struct ip_hdr *)rambuf->payload;
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
/* When not using a static buffer, create a chain of pbufs.
* The first will be a PBUF_RAM holding the link and IP header.
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
* but limited to the size of an mtu.
*/
rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM);
if (rambuf == NULL) {
goto memerr;
}
LWIP_ASSERT("this needs a pbuf in one piece!",
(rambuf->len >= (IP_HLEN)));
SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
iphdr = (struct ip_hdr *)rambuf->payload;
left_to_copy = fragsize;
while (left_to_copy) {
struct pbuf_custom_ref *pcr;
u16_t plen = (u16_t)(p->len - poff);
LWIP_ASSERT("p->len >= poff", p->len >= poff);
newpbuflen = LWIP_MIN(left_to_copy, plen);
/* Is this pbuf already empty? */
if (!newpbuflen) {
poff = 0;
p = p->next;
continue;
}
pcr = ip_frag_alloc_pbuf_custom_ref();
if (pcr == NULL) {
pbuf_free(rambuf);
goto memerr;
}
/* Mirror this pbuf, although we might not need all of it. */
newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc,
(u8_t *)p->payload + poff, newpbuflen);
if (newpbuf == NULL) {
ip_frag_free_pbuf_custom_ref(pcr);
pbuf_free(rambuf);
goto memerr;
}
pbuf_ref(p);
pcr->original = p;
pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
/* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
* so that it is removed when pbuf_dechain is later called on rambuf.
*/
pbuf_cat(rambuf, newpbuf);
left_to_copy = (u16_t)(left_to_copy - newpbuflen);
if (left_to_copy) {
poff = 0;
p = p->next;
}
}
poff = (u16_t)(poff + newpbuflen);
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
/* Correct header */
last = (left <= netif->mtu - IP_HLEN);
/* Set new offset and MF flag */
tmp = (IP_OFFMASK & (ofo));
if (!last || mf_set) {
/* the last fragment has MF set if the input frame had it */
tmp = tmp | IP_MF;
}
IPH_OFFSET_SET(iphdr, lwip_htons(tmp));
IPH_LEN_SET(iphdr, lwip_htons((u16_t)(fragsize + IP_HLEN)));
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
}
#endif /* CHECKSUM_GEN_IP */
/* No need for separate header pbuf - we allowed room for it in rambuf
* when allocated.
*/
netif->output(netif, rambuf, dest);
IPFRAG_STATS_INC(ip_frag.xmit);
/* Unfortunately we can't reuse rambuf - the hardware may still be
* using the buffer. Instead we free it (and the ensuing chain) and
* recreate it next time round the loop. If we're lucky the hardware
* will have already sent the packet, the free will really free, and
* there will be zero memory penalty.
*/
pbuf_free(rambuf);
left = (u16_t)(left - fragsize);
ofo = (u16_t)(ofo + nfb);
}
MIB2_STATS_INC(mib2.ipfragoks);
return ERR_OK;
memerr:
MIB2_STATS_INC(mib2.ipfragfails);
return ERR_MEM;
}
#endif /* IP_FRAG */
#endif /* LWIP_IPV4 */
File diff suppressed because it is too large. Load diff
+447
View File
@@ -0,0 +1,447 @@
/**
* @file
* Dynamic pool memory manager
*
* lwIP has dedicated pools for many structures (netconn, protocol control blocks,
* packet buffers, ...). All these pools are managed here.
*
* @defgroup mempool Memory pools
* @ingroup infrastructure
* Custom memory pools
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include <string.h>
/* Make sure we include everything we need for size calculation required by memp_std.h */
#include "lwip/pbuf.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/altcp.h"
#include "lwip/ip4_frag.h"
#include "lwip/netbuf.h"
#include "lwip/api.h"
#include "lwip/priv/tcpip_priv.h"
#include "lwip/priv/api_msg.h"
#include "lwip/priv/sockets_priv.h"
#include "lwip/etharp.h"
#include "lwip/igmp.h"
#include "lwip/timeouts.h"
/* needed by default MEMP_NUM_SYS_TIMEOUT */
#include "netif/ppp/ppp_opts.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "lwip/priv/nd6_priv.h"
#include "lwip/ip6_frag.h"
#include "lwip/mld6.h"
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
#include "lwip/priv/memp_std.h"
const struct memp_desc *const memp_pools[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
#include "lwip/priv/memp_std.h"
};
#ifdef LWIP_HOOK_FILENAME
#include LWIP_HOOK_FILENAME
#endif
#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
#undef MEMP_OVERFLOW_CHECK
/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
#define MEMP_OVERFLOW_CHECK 1
#endif
#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC
/**
* Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
*/
static int
memp_sanity(const struct memp_desc *desc)
{
struct memp *t, *h;
t = *desc->tab;
if (t != NULL) {
for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
h = ((h->next != NULL) ? h->next->next : NULL)) {
if (t == h) {
return 0;
}
}
}
return 1;
}
#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */
#if MEMP_OVERFLOW_CHECK
/**
* Check if a memp element was victim of an overflow or underflow
* (e.g. the restricted area after/before it has been altered)
*
* @param p the memp element to check
* @param desc the pool p comes from
*/
static void
memp_overflow_check_element(struct memp *p, const struct memp_desc *desc)
{
mem_overflow_check_raw((u8_t *)p + MEMP_SIZE, desc->size, "pool ", desc->desc);
}
/**
* Initialize the restricted area of on memp element.
*/
static void
memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
{
mem_overflow_init_raw((u8_t *)p + MEMP_SIZE, desc->size);
}
#if MEMP_OVERFLOW_CHECK >= 2
/**
* Do an overflow check for all elements in every pool.
*
* @see memp_overflow_check_element for a description of the check
*/
static void
memp_overflow_check_all(void)
{
u16_t i, j;
struct memp *p;
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
for (i = 0; i < MEMP_MAX; ++i) {
p = (struct memp *)LWIP_MEM_ALIGN(memp_pools[i]->base);
for (j = 0; j < memp_pools[i]->num; ++j) {
memp_overflow_check_element(p, memp_pools[i]);
p = LWIP_ALIGNMENT_CAST(struct memp *, ((u8_t *)p + MEMP_SIZE + memp_pools[i]->size + MEM_SANITY_REGION_AFTER_ALIGNED));
}
}
SYS_ARCH_UNPROTECT(old_level);
}
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
#endif /* MEMP_OVERFLOW_CHECK */
/**
* Initialize custom memory pool.
* Related functions: memp_malloc_pool, memp_free_pool
*
* @param desc pool to initialize
*/
void
memp_init_pool(const struct memp_desc *desc)
{
#if MEMP_MEM_MALLOC
LWIP_UNUSED_ARG(desc);
#else
int i;
struct memp *memp;
*desc->tab = NULL;
memp = (struct memp *)LWIP_MEM_ALIGN(desc->base);
#if MEMP_MEM_INIT
/* force memset on pool memory */
memset(memp, 0, (size_t)desc->num * (MEMP_SIZE + desc->size
#if MEMP_OVERFLOW_CHECK
+ MEM_SANITY_REGION_AFTER_ALIGNED
#endif
));
#endif
/* create a linked list of memp elements */
for (i = 0; i < desc->num; ++i) {
memp->next = *desc->tab;
*desc->tab = memp;
#if MEMP_OVERFLOW_CHECK
memp_overflow_init_element(memp, desc);
#endif /* MEMP_OVERFLOW_CHECK */
/* cast through void* to get rid of alignment warnings */
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
#if MEMP_OVERFLOW_CHECK
+ MEM_SANITY_REGION_AFTER_ALIGNED
#endif
);
}
#if MEMP_STATS
desc->stats->avail = desc->num;
#endif /* MEMP_STATS */
#endif /* !MEMP_MEM_MALLOC */
#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
desc->stats->name = desc->desc;
#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
}
/**
* Initializes lwIP built-in pools.
* Related functions: memp_malloc, memp_free
*
* Carves out memp_memory into linked lists for each pool-type.
*/
void
memp_init(void)
{
u16_t i;
/* for every pool: */
for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {
memp_init_pool(memp_pools[i]);
#if LWIP_STATS && MEMP_STATS
lwip_stats.memp[i] = memp_pools[i]->stats;
#endif
}
#if MEMP_OVERFLOW_CHECK >= 2
/* check everything a first time to see if it worked */
memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
}
static void *
#if !MEMP_OVERFLOW_CHECK
do_memp_malloc_pool(const struct memp_desc *desc)
#else
do_memp_malloc_pool_fn(const struct memp_desc *desc, const char *file, const int line)
#endif
{
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
#if MEMP_MEM_MALLOC
memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));
SYS_ARCH_PROTECT(old_level);
#else /* MEMP_MEM_MALLOC */
SYS_ARCH_PROTECT(old_level);
memp = *desc->tab;
#endif /* MEMP_MEM_MALLOC */
if (memp != NULL) {
#if !MEMP_MEM_MALLOC
#if MEMP_OVERFLOW_CHECK == 1
memp_overflow_check_element(memp, desc);
#endif /* MEMP_OVERFLOW_CHECK */
*desc->tab = memp->next;
#if MEMP_OVERFLOW_CHECK
memp->next = NULL;
#endif /* MEMP_OVERFLOW_CHECK */
#endif /* !MEMP_MEM_MALLOC */
#if MEMP_OVERFLOW_CHECK
memp->file = file;
memp->line = line;
#if MEMP_MEM_MALLOC
memp_overflow_init_element(memp, desc);
#endif /* MEMP_MEM_MALLOC */
#endif /* MEMP_OVERFLOW_CHECK */
LWIP_ASSERT("memp_malloc: memp properly aligned",
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
#if MEMP_STATS
desc->stats->used++;
if (desc->stats->used > desc->stats->max) {
desc->stats->max = desc->stats->used;
}
#endif
SYS_ARCH_UNPROTECT(old_level);
/* cast through u8_t* to get rid of alignment warnings */
return ((u8_t *)memp + MEMP_SIZE);
} else {
#if MEMP_STATS
desc->stats->err++;
#endif
SYS_ARCH_UNPROTECT(old_level);
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc));
}
return NULL;
}
/**
* Get an element from a custom pool.
*
* @param desc the pool to get an element from
*
* @return a pointer to the allocated memory or a NULL pointer on error
*/
void *
#if !MEMP_OVERFLOW_CHECK
memp_malloc_pool(const struct memp_desc *desc)
#else
memp_malloc_pool_fn(const struct memp_desc *desc, const char *file, const int line)
#endif
{
LWIP_ASSERT("invalid pool desc", desc != NULL);
if (desc == NULL) {
return NULL;
}
#if !MEMP_OVERFLOW_CHECK
return do_memp_malloc_pool(desc);
#else
return do_memp_malloc_pool_fn(desc, file, line);
#endif
}
/**
* Get an element from a specific pool.
*
* @param type the pool to get an element from
*
* @return a pointer to the allocated memory or a NULL pointer on error
*/
void *
#if !MEMP_OVERFLOW_CHECK
memp_malloc(memp_t type)
#else
memp_malloc_fn(memp_t type, const char *file, const int line)
#endif
{
void *memp;
LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
#if MEMP_OVERFLOW_CHECK >= 2
memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
#if !MEMP_OVERFLOW_CHECK
memp = do_memp_malloc_pool(memp_pools[type]);
#else
memp = do_memp_malloc_pool_fn(memp_pools[type], file, line);
#endif
return memp;
}
static void
do_memp_free_pool(const struct memp_desc *desc, void *mem)
{
struct memp *memp;
SYS_ARCH_DECL_PROTECT(old_level);
LWIP_ASSERT("memp_free: mem properly aligned",
((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
/* cast through void* to get rid of alignment warnings */
memp = (struct memp *)(void *)((u8_t *)mem - MEMP_SIZE);
SYS_ARCH_PROTECT(old_level);
#if MEMP_OVERFLOW_CHECK == 1
memp_overflow_check_element(memp, desc);
#endif /* MEMP_OVERFLOW_CHECK */
#if MEMP_STATS
desc->stats->used--;
#endif
#if MEMP_MEM_MALLOC
LWIP_UNUSED_ARG(desc);
SYS_ARCH_UNPROTECT(old_level);
mem_free(memp);
#else /* MEMP_MEM_MALLOC */
memp->next = *desc->tab;
*desc->tab = memp;
#if MEMP_SANITY_CHECK
LWIP_ASSERT("memp sanity", memp_sanity(desc));
#endif /* MEMP_SANITY_CHECK */
SYS_ARCH_UNPROTECT(old_level);
#endif /* !MEMP_MEM_MALLOC */
}
/**
* Put a custom pool element back into its pool.
*
* @param desc the pool where to put mem
* @param mem the memp element to free
*/
void
memp_free_pool(const struct memp_desc *desc, void *mem)
{
LWIP_ASSERT("invalid pool desc", desc != NULL);
if ((desc == NULL) || (mem == NULL)) {
return;
}
do_memp_free_pool(desc, mem);
}
/**
* Put an element back into its pool.
*
* @param type the pool where to put mem
* @param mem the memp element to free
*/
void
memp_free(memp_t type, void *mem)
{
#ifdef LWIP_HOOK_MEMP_AVAILABLE
struct memp *old_first;
#endif
LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
if (mem == NULL) {
return;
}
#if MEMP_OVERFLOW_CHECK >= 2
memp_overflow_check_all();
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
#ifdef LWIP_HOOK_MEMP_AVAILABLE
old_first = *memp_pools[type]->tab;
#endif
do_memp_free_pool(memp_pools[type], mem);
#ifdef LWIP_HOOK_MEMP_AVAILABLE
if (old_first == NULL) {
LWIP_HOOK_MEMP_AVAILABLE(type);
}
#endif
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+671
View File
@@ -0,0 +1,671 @@
/**
* @file
* Implementation of raw protocol PCBs for low-level handling of
* different types of protocols besides (or overriding) those
* already available in lwIP.\n
* See also @ref raw_raw
*
* @defgroup raw_raw RAW
* @ingroup callbackstyle_api
* Implementation of raw protocol PCBs for low-level handling of
* different types of protocols besides (or overriding) those
* already available in lwIP.\n
* @see @ref api
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/raw.h"
#include "lwip/priv/raw_priv.h"
#include "lwip/stats.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
#include "lwip/inet_chksum.h"
#include <string.h>
/** The list of RAW PCBs */
static struct raw_pcb *raw_pcbs;
static u8_t
raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast)
{
LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */
/* check if PCB is bound to specific netif */
if ((pcb->netif_idx != NETIF_NO_INDEX) &&
(pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) {
return 0;
}
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: PCBs listening to any IP type also listen to any IP address */
if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
#if IP_SOF_BROADCAST_RECV
if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) {
return 0;
}
#endif /* IP_SOF_BROADCAST_RECV */
return 1;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
/* Only need to check PCB if incoming IP version matches PCB IP version */
if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) {
#if LWIP_IPV4
/* Special case: IPv4 broadcast: receive all broadcasts
* Note: broadcast variable can only be 1 if it is an IPv4 broadcast */
if (broadcast != 0) {
#if IP_SOF_BROADCAST_RECV
if (ip_get_option(pcb, SOF_BROADCAST))
#endif /* IP_SOF_BROADCAST_RECV */
{
if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) {
return 1;
}
}
} else
#endif /* LWIP_IPV4 */
/* Handle IPv4 and IPv6: catch all or exact match */
if (ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
return 1;
}
}
return 0;
}
/**
* Determine if in incoming IP packet is covered by a RAW PCB
* and if so, pass it to a user-provided receive callback function.
*
* Given an incoming IP datagram (as a chain of pbufs) this function
* finds a corresponding RAW PCB and calls the corresponding receive
* callback function.
*
* @param p pbuf to be demultiplexed to a RAW PCB.
* @param inp network interface on which the datagram was received.
* @return - 1 if the packet has been eaten by a RAW PCB receive
* callback function. The caller MAY NOT not reference the
* packet any longer, and MAY NOT call pbuf_free().
* @return - 0 if packet is not eaten (pbuf is still referenced by the
* caller).
*
*/
raw_input_state_t
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb, *prev;
s16_t proto;
raw_input_state_t ret = RAW_INPUT_NONE;
u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif());
LWIP_UNUSED_ARG(inp);
#if LWIP_IPV6
#if LWIP_IPV4
if (IP_HDR_GET_VERSION(p->payload) == 6)
#endif /* LWIP_IPV4 */
{
struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
proto = IP6H_NEXTH(ip6hdr);
}
#if LWIP_IPV4
else
#endif /* LWIP_IPV4 */
#endif /* LWIP_IPV6 */
#if LWIP_IPV4
{
proto = IPH_PROTO((struct ip_hdr *)p->payload);
}
#endif /* LWIP_IPV4 */
prev = NULL;
pcb = raw_pcbs;
/* loop through all raw pcbs until the packet is eaten by one */
/* this allows multiple pcbs to match against the packet by design */
while (pcb != NULL) {
if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) &&
(((pcb->flags & RAW_FLAGS_CONNECTED) == 0) ||
ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) {
/* receive callback function available? */
if (pcb->recv != NULL) {
u8_t eaten;
#ifndef LWIP_NOASSERT
void *old_payload = p->payload;
#endif
ret = RAW_INPUT_DELIVERED;
/* the receive callback function did not eat the packet? */
eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
if (eaten != 0) {
/* receive function ate the packet */
p = NULL;
if (prev != NULL) {
/* move the pcb to the front of raw_pcbs so that is
found faster next time */
prev->next = pcb->next;
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return RAW_INPUT_EATEN;
} else {
/* sanity-check that the receive callback did not alter the pbuf */
LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet",
p->payload == old_payload);
}
}
/* no receive callback function was set for this raw PCB */
}
/* drop the packet */
prev = pcb;
pcb = pcb->next;
}
return ret;
}
/**
* @ingroup raw_raw
* Bind a RAW PCB.
*
* @param pcb RAW PCB to be bound with a local address ipaddr.
* @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to
* bind to all local interfaces.
*
* @return lwIP error code.
* - ERR_OK. Successful. No error occurred.
* - ERR_USE. The specified IP address is already bound to by
* another RAW PCB.
*
* @see raw_disconnect()
*/
err_t
raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{
LWIP_ASSERT_CORE_LOCKED();
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
#if LWIP_IPV6 && LWIP_IPV6_SCOPES
/* If the given IP address should have a zone but doesn't, assign one now.
* This is legacy support: scope-aware callers should always provide properly
* zoned source addresses. */
if (IP_IS_V6(&pcb->local_ip) &&
ip6_addr_lacks_zone(ip_2_ip6(&pcb->local_ip), IP6_UNKNOWN)) {
ip6_addr_select_zone(ip_2_ip6(&pcb->local_ip), ip_2_ip6(&pcb->local_ip));
}
#endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */
return ERR_OK;
}
/**
* @ingroup raw_raw
* Bind an RAW PCB to a specific netif.
* After calling this function, all packets received via this PCB
* are guaranteed to have come in via the specified netif, and all
* outgoing packets will go out via the specified netif.
*
* @param pcb RAW PCB to be bound with netif.
* @param netif netif to bind to. Can be NULL.
*
* @see raw_disconnect()
*/
void
raw_bind_netif(struct raw_pcb *pcb, const struct netif *netif)
{
LWIP_ASSERT_CORE_LOCKED();
if (netif != NULL) {
pcb->netif_idx = netif_get_index(netif);
} else {
pcb->netif_idx = NETIF_NO_INDEX;
}
}
/**
* @ingroup raw_raw
* Connect an RAW PCB. This function is required by upper layers
* of lwip. Using the raw api you could use raw_sendto() instead
*
* This will associate the RAW PCB with the remote address.
*
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
* @param ipaddr remote IP address to connect with.
*
* @return lwIP error code
*
* @see raw_disconnect() and raw_sendto()
*/
err_t
raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{
LWIP_ASSERT_CORE_LOCKED();
if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
#if LWIP_IPV6 && LWIP_IPV6_SCOPES
/* If the given IP address should have a zone but doesn't, assign one now,
* using the bound address to make a more informed decision when possible. */
if (IP_IS_V6(&pcb->remote_ip) &&
ip6_addr_lacks_zone(ip_2_ip6(&pcb->remote_ip), IP6_UNKNOWN)) {
ip6_addr_select_zone(ip_2_ip6(&pcb->remote_ip), ip_2_ip6(&pcb->local_ip));
}
#endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */
raw_set_flags(pcb, RAW_FLAGS_CONNECTED);
return ERR_OK;
}
/**
* @ingroup raw_raw
* Disconnect a RAW PCB.
*
* @param pcb the raw pcb to disconnect.
*/
void
raw_disconnect(struct raw_pcb *pcb)
{
LWIP_ASSERT_CORE_LOCKED();
/* reset remote address association */
#if LWIP_IPV4 && LWIP_IPV6
if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE);
} else {
#endif
ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip);
#if LWIP_IPV4 && LWIP_IPV6
}
#endif
pcb->netif_idx = NETIF_NO_INDEX;
/* mark PCB as unconnected */
raw_clear_flags(pcb, RAW_FLAGS_CONNECTED);
}
/**
* @ingroup raw_raw
* Set the callback function for received packets that match the
* raw PCB's protocol and binding.
*
* The callback function MUST either
* - eat the packet by calling pbuf_free() and returning non-zero. The
* packet will not be passed to other raw PCBs or other protocol layers.
* - not free the packet, and return zero. The packet will be matched
* against further PCBs and/or forwarded to another protocol layers.
*/
void
raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
{
LWIP_ASSERT_CORE_LOCKED();
/* remember recv() callback and user data */
pcb->recv = recv;
pcb->recv_arg = recv_arg;
}
/**
* @ingroup raw_raw
* Send the raw IP packet to the given address. An IP header will be prepended
* to the packet, unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that
* case, the packet must include an IP header, which will then be sent as is.
*
* @param pcb the raw pcb which to send
* @param p the IP payload to send
* @param ipaddr the destination address of the IP packet
*
*/
err_t
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
{
struct netif *netif;
const ip_addr_t *src_ip;
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
return ERR_VAL;
}
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
if (pcb->netif_idx != NETIF_NO_INDEX) {
netif = netif_get_by_index(pcb->netif_idx);
} else {
#if LWIP_MULTICAST_TX_OPTIONS
netif = NULL;
if (ip_addr_ismulticast(ipaddr)) {
/* For multicast-destined packets, use the user-provided interface index to
* determine the outgoing interface, if an interface index is set and a
* matching netif can be found. Otherwise, fall back to regular routing. */
netif = netif_get_by_index(pcb->mcast_ifindex);
}
if (netif == NULL)
#endif /* LWIP_MULTICAST_TX_OPTIONS */
{
netif = ip_route(&pcb->local_ip, ipaddr);
}
}
if (netif == NULL) {
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr);
return ERR_RTE;
}
if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = ip_netif_get_local_ip(netif, ipaddr);
#if LWIP_IPV6
if (src_ip == NULL) {
return ERR_RTE;
}
#endif /* LWIP_IPV6 */
} else {
/* use RAW PCB local IP address as source address */
src_ip = &pcb->local_ip;
}
return raw_sendto_if_src(pcb, p, ipaddr, netif, src_ip);
}
/**
* @ingroup raw_raw
* Send the raw IP packet to the given address, using a particular outgoing
* netif and source IP address. An IP header will be prepended to the packet,
* unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that case, the
* packet must include an IP header, which will then be sent as is.
*
* @param pcb RAW PCB used to send the data
* @param p chain of pbufs to be sent
* @param dst_ip destination IP address
* @param netif the netif used for sending
* @param src_ip source IP address
*/
err_t
raw_sendto_if_src(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
struct netif *netif, const ip_addr_t *src_ip)
{
err_t err;
struct pbuf *q; /* q will be sent down the stack */
u16_t header_size;
u8_t ttl;
LWIP_ASSERT_CORE_LOCKED();
if ((pcb == NULL) || (dst_ip == NULL) || (netif == NULL) || (src_ip == NULL) ||
!IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) {
return ERR_VAL;
}
header_size = (
#if LWIP_IPV4 && LWIP_IPV6
IP_IS_V6(dst_ip) ? IP6_HLEN : IP_HLEN);
#elif LWIP_IPV4
IP_HLEN);
#else
IP6_HLEN);
#endif
/* Handle the HDRINCL option as an exception: none of the code below applies
* to this case, and sending the packet needs to be done differently too. */
if (pcb->flags & RAW_FLAGS_HDRINCL) {
/* A full header *must* be present in the first pbuf of the chain, as the
* output routines may access its fields directly. */
if (p->len < header_size) {
return ERR_VAL;
}
/* @todo multicast loop support, if at all desired for this scenario.. */
NETIF_SET_HINTS(netif, &pcb->netif_hints);
err = ip_output_if_hdrincl(p, src_ip, dst_ip, netif);
NETIF_RESET_HINTS(netif);
return err;
}
/* packet too large to add an IP header without causing an overflow? */
if ((u16_t)(p->tot_len + header_size) < p->tot_len) {
return ERR_MEM;
}
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_add_header(p, header_size)) {
/* allocate header in new pbuf */
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
/* new header pbuf could not be allocated? */
if (q == NULL) {
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
return ERR_MEM;
}
if (p->tot_len != 0) {
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
}
/* { first pbuf q points to header pbuf } */
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
} else {
/* first pbuf q equals given pbuf */
q = p;
if (pbuf_remove_header(q, header_size)) {
LWIP_ASSERT("Can't restore header we just removed!", 0);
return ERR_MEM;
}
}
#if IP_SOF_BROADCAST
if (IP_IS_V4(dst_ip)) {
/* broadcast filter? */
if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) {
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
}
return ERR_VAL;
}
}
#endif /* IP_SOF_BROADCAST */
/* Multicast Loop? */
#if LWIP_MULTICAST_TX_OPTIONS
if (((pcb->flags & RAW_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) {
q->flags |= PBUF_FLAG_MCASTLOOP;
}
#endif /* LWIP_MULTICAST_TX_OPTIONS */
#if LWIP_IPV6
/* If requested, based on the IPV6_CHECKSUM socket option per RFC3542,
compute the checksum and update the checksum in the payload. */
if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) {
u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip));
LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2));
SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t));
}
#endif
/* Determine TTL to use */
#if LWIP_MULTICAST_TX_OPTIONS
ttl = (ip_addr_ismulticast(dst_ip) ? raw_get_multicast_ttl(pcb) : pcb->ttl);
#else /* LWIP_MULTICAST_TX_OPTIONS */
ttl = pcb->ttl;
#endif /* LWIP_MULTICAST_TX_OPTIONS */
NETIF_SET_HINTS(netif, &pcb->netif_hints);
err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif);
NETIF_RESET_HINTS(netif);
/* did we chain a header earlier? */
if (q != p) {
/* free the header */
pbuf_free(q);
}
return err;
}
/**
* @ingroup raw_raw
* Send the raw IP packet to the address given by raw_connect()
*
* @param pcb the raw pcb which to send
* @param p the IP payload to send
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_sendto(pcb, p, &pcb->remote_ip);
}
/**
* @ingroup raw_raw
* Remove an RAW PCB.
*
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
* RAW PCB's and the data structure is freed from memory.
*
* @see raw_new()
*/
void
raw_remove(struct raw_pcb *pcb)
{
struct raw_pcb *pcb2;
LWIP_ASSERT_CORE_LOCKED();
/* pcb to be removed is first in list? */
if (raw_pcbs == pcb) {
/* make list start at 2nd pcb */
raw_pcbs = raw_pcbs->next;
/* pcb not 1st in list */
} else {
for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
/* find pcb in raw_pcbs list */
if (pcb2->next != NULL && pcb2->next == pcb) {
/* remove pcb from list */
pcb2->next = pcb->next;
break;
}
}
}
memp_free(MEMP_RAW_PCB, pcb);
}
/**
* @ingroup raw_raw
* Create a RAW PCB.
*
* @return The RAW PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
*
* @see raw_remove()
*/
struct raw_pcb *
raw_new(u8_t proto)
{
struct raw_pcb *pcb;
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
LWIP_ASSERT_CORE_LOCKED();
pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB);
/* could allocate RAW PCB? */
if (pcb != NULL) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct raw_pcb));
pcb->protocol = proto;
pcb->ttl = RAW_TTL;
#if LWIP_MULTICAST_TX_OPTIONS
raw_set_multicast_ttl(pcb, RAW_TTL);
#endif /* LWIP_MULTICAST_TX_OPTIONS */
pcb->next = raw_pcbs;
raw_pcbs = pcb;
}
return pcb;
}
/**
* @ingroup raw_raw
* Create a RAW PCB for specific IP type.
*
* @return The RAW PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
* @param type IP address type, see @ref lwip_ip_addr_type definitions.
* If you want to listen to IPv4 and IPv6 (dual-stack) packets,
* supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
* @param proto the protocol number (next header) of the IPv6 packet payload
* (e.g. IP6_NEXTH_ICMP6)
*
* @see raw_remove()
*/
struct raw_pcb *
raw_new_ip_type(u8_t type, u8_t proto)
{
struct raw_pcb *pcb;
LWIP_ASSERT_CORE_LOCKED();
pcb = raw_new(proto);
#if LWIP_IPV4 && LWIP_IPV6
if (pcb != NULL) {
IP_SET_TYPE_VAL(pcb->local_ip, type);
IP_SET_TYPE_VAL(pcb->remote_ip, type);
}
#else /* LWIP_IPV4 && LWIP_IPV6 */
LWIP_UNUSED_ARG(type);
#endif /* LWIP_IPV4 && LWIP_IPV6 */
return pcb;
}
/** This function is called from netif.c when address is changed
*
* @param old_addr IP address of the netif before change
* @param new_addr IP address of the netif after change
*/
void raw_netif_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr)
{
struct raw_pcb *rpcb;
if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) {
for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) {
/* PCB bound to current local interface address? */
if (ip_addr_cmp(&rpcb->local_ip, old_addr)) {
/* The PCB is bound to the old ipaddr and
* is set to bound to the new one instead */
ip_addr_copy(rpcb->local_ip, *new_addr);
}
}
}
}
#endif /* LWIP_RAW */
+169
View File
@@ -0,0 +1,169 @@
/**
* @file
* Statistics module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "lwip/opt.h"
#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */
#include "lwip/def.h"
#include "lwip/stats.h"
#include "lwip/mem.h"
#include "lwip/debug.h"
#include <string.h>
struct stats_ lwip_stats;
void
stats_init(void)
{
#ifdef LWIP_DEBUG
#if MEM_STATS
lwip_stats.mem.name = "MEM";
#endif /* MEM_STATS */
#endif /* LWIP_DEBUG */
}
#if LWIP_STATS_DISPLAY
void
stats_display_proto(struct stats_proto *proto, const char *name)
{
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv));
LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw));
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop));
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr));
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr));
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr));
LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr));
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr));
LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr));
LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err));
LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit));
}
#if IGMP_STATS || MLD6_STATS
void
stats_display_igmp(struct stats_igmp *igmp, const char *name)
{
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr));
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr));
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr));
LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1));
LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group));
LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general));
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report));
}
#endif /* IGMP_STATS || MLD6_STATS */
#if MEM_STATS || MEMP_STATS
void
stats_display_mem(struct stats_mem *mem, const char *name)
{
LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name));
LWIP_PLATFORM_DIAG(("avail: %"MEM_SIZE_F"\n\t", mem->avail));
LWIP_PLATFORM_DIAG(("used: %"MEM_SIZE_F"\n\t", mem->used));
LWIP_PLATFORM_DIAG(("max: %"MEM_SIZE_F"\n\t", mem->max));
LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n", mem->err));
}
#if MEMP_STATS
void
stats_display_memp(struct stats_mem *mem, int idx)
{
if (idx < MEMP_MAX) {
stats_display_mem(mem, mem->name);
}
}
#endif /* MEMP_STATS */
#endif /* MEM_STATS || MEMP_STATS */
#if SYS_STATS
void
stats_display_sys(struct stats_sys *sys)
{
LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
LWIP_PLATFORM_DIAG(("sem.used: %"STAT_COUNTER_F"\n\t", sys->sem.used));
LWIP_PLATFORM_DIAG(("sem.max: %"STAT_COUNTER_F"\n\t", sys->sem.max));
LWIP_PLATFORM_DIAG(("sem.err: %"STAT_COUNTER_F"\n\t", sys->sem.err));
LWIP_PLATFORM_DIAG(("mutex.used: %"STAT_COUNTER_F"\n\t", sys->mutex.used));
LWIP_PLATFORM_DIAG(("mutex.max: %"STAT_COUNTER_F"\n\t", sys->mutex.max));
LWIP_PLATFORM_DIAG(("mutex.err: %"STAT_COUNTER_F"\n\t", sys->mutex.err));
LWIP_PLATFORM_DIAG(("mbox.used: %"STAT_COUNTER_F"\n\t", sys->mbox.used));
LWIP_PLATFORM_DIAG(("mbox.max: %"STAT_COUNTER_F"\n\t", sys->mbox.max));
LWIP_PLATFORM_DIAG(("mbox.err: %"STAT_COUNTER_F"\n", sys->mbox.err));
}
#endif /* SYS_STATS */
void
stats_display(void)
{
s16_t i;
LINK_STATS_DISPLAY();
ETHARP_STATS_DISPLAY();
IPFRAG_STATS_DISPLAY();
IP6_FRAG_STATS_DISPLAY();
IP_STATS_DISPLAY();
ND6_STATS_DISPLAY();
IP6_STATS_DISPLAY();
IGMP_STATS_DISPLAY();
MLD6_STATS_DISPLAY();
ICMP_STATS_DISPLAY();
ICMP6_STATS_DISPLAY();
UDP_STATS_DISPLAY();
TCP_STATS_DISPLAY();
MEM_STATS_DISPLAY();
for (i = 0; i < MEMP_MAX; i++) {
MEMP_STATS_DISPLAY(i);
}
SYS_STATS_DISPLAY();
}
#endif /* LWIP_STATS_DISPLAY */
#endif /* LWIP_STATS */
+148
View File
@@ -0,0 +1,148 @@
/**
* @file
* lwIP Operating System abstraction
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/**
* @defgroup sys_layer Porting (system abstraction layer)
* @ingroup lwip
*
* @defgroup sys_os OS abstraction layer
* @ingroup sys_layer
* No need to implement functions in this section in NO_SYS mode.
* The OS-specific code should be implemented in arch/sys_arch.h
* and sys_arch.c of your port.
*
* The operating system emulation layer provides a common interface
* between the lwIP code and the underlying operating system kernel. The
* general idea is that porting lwIP to new architectures requires only
* small changes to a few header files and a new sys_arch
* implementation. It is also possible to do a sys_arch implementation
* that does not rely on any underlying operating system.
*
* The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full
* lwIP functionality, multiple threads support can be implemented in the
* sys_arch, but this is not required for the basic lwIP
* functionality. Timer scheduling is implemented in lwIP, but can be implemented
* by the sys_arch port (LWIP_TIMERS_CUSTOM==1).
*
* In addition to the source file providing the functionality of sys_arch,
* the OS emulation layer must provide several header files defining
* macros used throughout lwip. The files required and the macros they
* must define are listed below the sys_arch description.
*
* Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that
* allows both using pointers or actual OS structures to be used. This way, memory
* required for such types can be either allocated in place (globally or on the
* stack) or on the heap (allocated internally in the "*_new()" functions).
*
* Note:
* -----
* Be careful with using mem_malloc() in sys_arch. When malloc() refers to
* mem_malloc() you can run into a circular function call problem. In mem.c
* mem_init() tries to allocate a semaphore using mem_malloc, which of course
* can't be performed when sys_arch uses mem_malloc.
*
* @defgroup sys_sem Semaphores
* @ingroup sys_os
* Semaphores can be either counting or binary - lwIP works with both
* kinds.
* Semaphores are represented by the type "sys_sem_t" which is typedef'd
* in the sys_arch.h file. Mailboxes are equivalently represented by the
* type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t".
* lwIP does not place any restrictions on how these types are represented
* internally.
*
* @defgroup sys_mutex Mutexes
* @ingroup sys_os
* Mutexes are recommended to correctly handle priority inversion,
* especially if you use LWIP_CORE_LOCKING .
*
* @defgroup sys_mbox Mailboxes
* @ingroup sys_os
* Mailboxes should be implemented as a queue which allows multiple messages
* to be posted (implementing as a rendez-vous point where only one message can be
* posted at a time can have a highly negative impact on performance). A message
* in a mailbox is just a pointer, nothing more.
*
* @defgroup sys_time Time
* @ingroup sys_layer
*
* @defgroup sys_prot Critical sections
* @ingroup sys_layer
* Used to protect short regions of code against concurrent access.
* - Your system is a bare-metal system (probably with an RTOS)
* and interrupts are under your control:
* Implement this as LockInterrupts() / UnlockInterrupts()
* - Your system uses an RTOS with deferred interrupt handling from a
* worker thread: Implement as a global mutex or lock/unlock scheduler
* - Your system uses a high-level OS with e.g. POSIX signals:
* Implement as a global mutex
*
* @defgroup sys_misc Misc
* @ingroup sys_os
*/
#include "lwip/opt.h"
#include "lwip/sys.h"
/* Most of the functions defined in sys.h must be implemented in the
* architecture-dependent file sys_arch.c */
#if !NO_SYS
#ifndef sys_msleep
/**
* Sleep for some ms. Timeouts are NOT processed while sleeping.
*
* @param ms number of milliseconds to sleep
*/
void
sys_msleep(u32_t ms)
{
if (ms > 0) {
sys_sem_t delaysem;
err_t err = sys_sem_new(&delaysem, 0);
if (err == ERR_OK) {
sys_arch_sem_wait(&delaysem, ms);
sys_sem_free(&delaysem);
}
}
}
#endif /* sys_msleep */
#endif /* !NO_SYS */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,451 @@
/**
* @file
* Stack-internal timers implementation.
* This file includes timer callbacks for stack-internal timers as well as
* functions to set up or stop timers and check for expired timers.
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
* Simon Goldschmidt
*
*/
#include "lwip/opt.h"
#include "lwip/timeouts.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/priv/tcpip_priv.h"
#include "lwip/ip4_frag.h"
#include "lwip/etharp.h"
#include "lwip/dhcp.h"
#include "lwip/autoip.h"
#include "lwip/igmp.h"
#include "lwip/dns.h"
#include "lwip/nd6.h"
#include "lwip/ip6_frag.h"
#include "lwip/mld6.h"
#include "lwip/dhcp6.h"
#include "lwip/sys.h"
#include "lwip/pbuf.h"
#if LWIP_DEBUG_TIMERNAMES
#define HANDLER(x) x, #x
#else /* LWIP_DEBUG_TIMERNAMES */
#define HANDLER(x) x
#endif /* LWIP_DEBUG_TIMERNAMES */
#define LWIP_MAX_TIMEOUT 0x7fffffff
/* Check if timer's expiry time is greater than time and care about u32_t wraparounds */
#define TIME_LESS_THAN(t, compare_to) ( (((u32_t)((t)-(compare_to))) > LWIP_MAX_TIMEOUT) ? 1 : 0 )
/** This array contains all stack-internal cyclic timers. To get the number of
* timers, use LWIP_ARRAYSIZE() */
const struct lwip_cyclic_timer lwip_cyclic_timers[] = {
#if LWIP_TCP
/* The TCP timer is a special case: it does not have to run always and
is triggered to start from TCP using tcp_timer_needed() */
{TCP_TMR_INTERVAL, HANDLER(tcp_tmr)},
#endif /* LWIP_TCP */
#if LWIP_IPV4
#if IP_REASSEMBLY
{IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)},
#endif /* IP_REASSEMBLY */
#if LWIP_ARP
{ARP_TMR_INTERVAL, HANDLER(etharp_tmr)},
#endif /* LWIP_ARP */
#if LWIP_DHCP
{DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)},
{DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)},
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
{AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)},
#endif /* LWIP_AUTOIP */
#if LWIP_IGMP
{IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)},
#endif /* LWIP_IGMP */
#endif /* LWIP_IPV4 */
#if LWIP_DNS
{DNS_TMR_INTERVAL, HANDLER(dns_tmr)},
#endif /* LWIP_DNS */
#if LWIP_IPV6
{ND6_TMR_INTERVAL, HANDLER(nd6_tmr)},
#if LWIP_IPV6_REASS
{IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)},
#endif /* LWIP_IPV6_REASS */
#if LWIP_IPV6_MLD
{MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)},
#endif /* LWIP_IPV6_MLD */
#if LWIP_IPV6_DHCP6
{DHCP6_TIMER_MSECS, HANDLER(dhcp6_tmr)},
#endif /* LWIP_IPV6_DHCP6 */
#endif /* LWIP_IPV6 */
};
const int lwip_num_cyclic_timers = LWIP_ARRAYSIZE(lwip_cyclic_timers);
#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM
/** The one and only timeout list */
static struct sys_timeo *next_timeout;
static u32_t current_timeout_due_time;
#if LWIP_TESTMODE
struct sys_timeo**
sys_timeouts_get_next_timeout(void)
{
return &next_timeout;
}
#endif
#if LWIP_TCP
/** global variable that shows if the tcp timer is currently scheduled or not */
static int tcpip_tcp_timer_active;
/**
* Timer callback function that calls tcp_tmr() and reschedules itself.
*
* @param arg unused argument
*/
static void
tcpip_tcp_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
/* call TCP timer handler */
tcp_tmr();
/* timer still needed? */
if (tcp_active_pcbs || tcp_tw_pcbs) {
/* restart timer */
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
} else {
/* disable timer */
tcpip_tcp_timer_active = 0;
}
}
/**
* Called from TCP_REG when registering a new PCB:
* the reason is to have the TCP timer only running when
* there are active (or time-wait) PCBs.
*/
void
tcp_timer_needed(void)
{
LWIP_ASSERT_CORE_LOCKED();
/* timer is off but needed again? */
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
/* enable and start timer */
tcpip_tcp_timer_active = 1;
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
}
}
#endif /* LWIP_TCP */
static void
#if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg, const char *handler_name)
#else /* LWIP_DEBUG_TIMERNAMES */
sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg)
#endif
{
struct sys_timeo *timeout, *t;
timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
if (timeout == NULL) {
LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
return;
}
timeout->next = NULL;
timeout->h = handler;
timeout->arg = arg;
timeout->time = abs_time;
#if LWIP_DEBUG_TIMERNAMES
timeout->handler_name = handler_name;
LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p abs_time=%"U32_F" handler=%s arg=%p\n",
(void *)timeout, abs_time, handler_name, (void *)arg));
#endif /* LWIP_DEBUG_TIMERNAMES */
if (next_timeout == NULL) {
next_timeout = timeout;
return;
}
if (TIME_LESS_THAN(timeout->time, next_timeout->time)) {
timeout->next = next_timeout;
next_timeout = timeout;
} else {
for (t = next_timeout; t != NULL; t = t->next) {
if ((t->next == NULL) || TIME_LESS_THAN(timeout->time, t->next->time)) {
timeout->next = t->next;
t->next = timeout;
break;
}
}
}
}
/**
* Timer callback function that calls cyclic->handler() and reschedules itself.
*
* @param arg unused argument
*/
#if !LWIP_TESTMODE
static
#endif
void
lwip_cyclic_timer(void *arg)
{
u32_t now;
u32_t next_timeout_time;
const struct lwip_cyclic_timer *cyclic = (const struct lwip_cyclic_timer *)arg;
#if LWIP_DEBUG_TIMERNAMES
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name));
#endif
cyclic->handler();
now = sys_now();
next_timeout_time = (u32_t)(current_timeout_due_time + cyclic->interval_ms); /* overflow handled by TIME_LESS_THAN macro */
if (TIME_LESS_THAN(next_timeout_time, now)) {
/* timer would immediately expire again -> "overload" -> restart without any correction */
#if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg, cyclic->handler_name);
#else
sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg);
#endif
} else {
/* correct cyclic interval with handler execution delay and sys_check_timeouts jitter */
#if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg, cyclic->handler_name);
#else
sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg);
#endif
}
}
/** Initialize this module */
void sys_timeouts_init(void)
{
size_t i;
/* tcp_tmr() at index 0 is started on demand */
for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
/* we have to cast via size_t to get rid of const warning
(this is OK as cyclic_timer() casts back to const* */
sys_timeout(lwip_cyclic_timers[i].interval_ms, lwip_cyclic_timer, LWIP_CONST_CAST(void *, &lwip_cyclic_timers[i]));
}
}
/**
* Create a one-shot timer (aka timeout). Timeouts are processed in the
* following cases:
* - while waiting for a message using sys_timeouts_mbox_fetch()
* - by calling sys_check_timeouts() (NO_SYS==1 only)
*
* @param msecs time in milliseconds after that the timer should expire
* @param handler callback function to call when msecs have elapsed
* @param arg argument to pass to the callback function
*/
#if LWIP_DEBUG_TIMERNAMES
void
sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char *handler_name)
#else /* LWIP_DEBUG_TIMERNAMES */
void
sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
#endif /* LWIP_DEBUG_TIMERNAMES */
{
u32_t next_timeout_time;
LWIP_ASSERT_CORE_LOCKED();
LWIP_ASSERT("Timeout time too long, max is LWIP_UINT32_MAX/4 msecs", msecs <= (LWIP_UINT32_MAX / 4));
next_timeout_time = (u32_t)(sys_now() + msecs); /* overflow handled by TIME_LESS_THAN macro */
#if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs(next_timeout_time, handler, arg, handler_name);
#else
sys_timeout_abs(next_timeout_time, handler, arg);
#endif
}
/**
* Go through timeout list (for this task only) and remove the first matching
* entry (subsequent entries remain untouched), even though the timeout has not
* triggered yet.
*
* @param handler callback function that would be called by the timeout
* @param arg callback argument that would be passed to handler
*/
void
sys_untimeout(sys_timeout_handler handler, void *arg)
{
struct sys_timeo *prev_t, *t;
LWIP_ASSERT_CORE_LOCKED();
if (next_timeout == NULL) {
return;
}
for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
if ((t->h == handler) && (t->arg == arg)) {
/* We have a match */
/* Unlink from previous in list */
if (prev_t == NULL) {
next_timeout = t->next;
} else {
prev_t->next = t->next;
}
memp_free(MEMP_SYS_TIMEOUT, t);
return;
}
}
return;
}
/**
* @ingroup lwip_nosys
* Handle timeouts for NO_SYS==1 (i.e. without using
* tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
* handler functions when timeouts expire.
*
* Must be called periodically from your main loop.
*/
void
sys_check_timeouts(void)
{
u32_t now;
LWIP_ASSERT_CORE_LOCKED();
/* Process only timers expired at the start of the function. */
now = sys_now();
do {
struct sys_timeo *tmptimeout;
sys_timeout_handler handler;
void *arg;
PBUF_CHECK_FREE_OOSEQ();
tmptimeout = next_timeout;
if (tmptimeout == NULL) {
return;
}
if (TIME_LESS_THAN(now, tmptimeout->time)) {
return;
}
/* Timeout has expired */
next_timeout = tmptimeout->next;
handler = tmptimeout->h;
arg = tmptimeout->arg;
current_timeout_due_time = tmptimeout->time;
#if LWIP_DEBUG_TIMERNAMES
if (handler != NULL) {
LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s t=%"U32_F" arg=%p\n",
tmptimeout->handler_name, sys_now() - tmptimeout->time, arg));
}
#endif /* LWIP_DEBUG_TIMERNAMES */
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (handler != NULL) {
handler(arg);
}
LWIP_TCPIP_THREAD_ALIVE();
/* Repeat until all expired timers have been called */
} while (1);
}
/** Rebase the timeout times to the current time.
* This is necessary if sys_check_timeouts() hasn't been called for a long
* time (e.g. while saving energy) to prevent all timer functions of that
* period being called.
*/
void
sys_restart_timeouts(void)
{
u32_t now;
u32_t base;
struct sys_timeo *t;
if (next_timeout == NULL) {
return;
}
now = sys_now();
base = next_timeout->time;
for (t = next_timeout; t != NULL; t = t->next) {
t->time = (t->time - base) + now;
}
}
/** Return the time left before the next timeout is due. If no timeouts are
* enqueued, returns 0xffffffff
*/
u32_t
sys_timeouts_sleeptime(void)
{
u32_t now;
LWIP_ASSERT_CORE_LOCKED();
if (next_timeout == NULL) {
return SYS_TIMEOUTS_SLEEPTIME_INFINITE;
}
now = sys_now();
if (TIME_LESS_THAN(next_timeout->time, now)) {
return 0;
} else {
u32_t ret = (u32_t)(next_timeout->time - now);
LWIP_ASSERT("invalid sleeptime", ret <= LWIP_MAX_TIMEOUT);
return ret;
}
}
#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
/* Satisfy the TCP code which calls this function */
void
tcp_timer_needed(void)
{
}
#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+192
View File
@@ -0,0 +1,192 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DHCPS_H__
#define __DHCPS_H__
//#include "sdkconfig.h"
#include <stdbool.h>
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct dhcps_state{
s16_t state;
} dhcps_state;
typedef struct dhcps_msg {
uint8_t op, htype, hlen, hops;// operation code, hw type, hw addr len, hops
uint8_t xid[4];// transaction id
uint16_t secs, flags; // seconds, flags
uint8_t ciaddr[4];// client ip addr
uint8_t yiaddr[4];// your ip addr
uint8_t siaddr[4];// server ip addr
uint8_t giaddr[4];// GW ip
uint8_t chaddr[16];// client hw address
uint8_t sname[64];// server name
uint8_t file[128];// boot filename
uint8_t options[312];
}dhcps_msg;
/* Defined in esp_misc.h */
typedef struct {
bool enable;
ip4_addr_t start_ip;
ip4_addr_t end_ip;
} dhcps_lease_t;
enum dhcps_offer_option{
OFFER_START = 0x00,
OFFER_ROUTER = 0x01,
OFFER_DNS = 0x02,
OFFER_END
};
/** @brief DHCP server's description of compile time configuration values in dhcpserver.c
*
* - DHCPS_DEBUG: Prints very detailed debug messages if set to 1, hardcoded to 0
* - USE_CLASS_B_NET: Use class B network mask if enabled, not-defined (could be enabled as CC_FLAGS)
* - MAX_STATION_NUM: Maximum number of clients, set to Kconfig value CONFIG_LWIP_DHCPS_MAX_STATION_NUM
* - LWIP_HOOK_DHCPS_POST_STATE: Used to inject user code after parsing DHCP message, not defined
* - could be enabled in lwipopts.h or via CC_FLAGS
* - basic usage of the hook to print hex representation of the entire option field is below:
* #define LWIP_HOOK_DHCPS_POST_STATE(msg, len, state) \
* ({ s16_t ret = state; if (state == DHCPS_STATE_ACK) { ESP_LOG_BUFFER_HEXDUMP("DHCPS",msg->options, 312, ESP_LOG_INFO);} ret; })
*/
/**
* @brief Definitions related to lease time, units and limits
*/
#define DHCPS_COARSE_TIMER_SECS 1
#define DHCPS_MAX_LEASE 0x64
#define DHCPS_LEASE_TIME_DEF (120)
#define DHCPS_LEASE_UNIT CONFIG_LWIP_DHCPS_LEASE_UNIT
struct dhcps_pool{
ip4_addr_t ip;
u8_t mac[6];
u32_t lease_timer;
};
typedef u32_t dhcps_time_t;
typedef u8_t dhcps_offer_t;
typedef struct {
dhcps_offer_t dhcps_offer;
dhcps_offer_t dhcps_dns;
dhcps_time_t dhcps_time;
dhcps_lease_t dhcps_poll;
} dhcps_options_t;
typedef void (*dhcps_cb_t)(void* cb_arg, u8_t client_ip[4], u8_t client_mac[6]);
static inline bool dhcps_router_enabled (dhcps_offer_t offer)
{
return (offer & OFFER_ROUTER) != 0;
}
static inline bool dhcps_dns_enabled (dhcps_offer_t offer)
{
return (offer & OFFER_DNS) != 0;
}
typedef struct dhcps_t dhcps_t;
/**
* @brief Creates new DHCP server object
*
* @return Pointer to the DHCP server handle on success, NULL on error
*/
dhcps_t *dhcps_new(void);
/**
* @brief Deletes supplied DHPC server object
*
* @warning This may not delete the handle immediately if the server wasn't
* stopped properly, but mark for deleting once the timer callback occurs
*
* @param dhcps Pointer to the DHCP handle
*/
void dhcps_delete(dhcps_t *dhcps);
/**
* @brief Starts the DHCP server on the specified network interface
*
* @param dhcps Pointer to the DHCP handle
* @param netif Pointer to the lwIP's network interface struct
* @param ip DHCP server's address
* @return ERR_ARG if invalid args, ERR_OK on success
*/
err_t dhcps_start(dhcps_t *dhcps, struct netif *netif, ip4_addr_t ip);
/**
* @brief Stops the DHCP server on the specified netif
* @param dhcps Pointer to the DHCP handle
* @param netif Pointer to the lwIP's network interface struct
* @return ERR_ARG if invalid args, ERR_OK on success
*/
err_t dhcps_stop(dhcps_t *dhcps, struct netif *netif);
/**
* @brief Gets the DHCP server option info
* @param dhcps Pointer to the DHCP handle
* @param op_id DHCP message option id
* @param opt_len DHCP message option length
* @return DHCP message option addr
*/
void *dhcps_option_info(dhcps_t *dhcps, u8_t op_id, u32_t opt_len);
/**
* @brief Sets the DHCP server option info
* @param dhcps Pointer to the DHCP handle
* @param op_id DHCP message option id
* @param opt_info DHCP message option info
* @param opt_len DHCP message option length
* @return ERR_ARG if invalid args, ERR_OK on success
*/
err_t dhcps_set_option_info(dhcps_t *dhcps, u8_t op_id, void *opt_info, u32_t opt_len);
/**
* @brief Tries to find IP address corresponding to the supplied MAC
* @param dhcps Pointer to the DHCP handle
* @param mac Supplied MAC address
* @param ip Pointer to the resultant IP address
* @return True if the IP address has been found
*/
bool dhcp_search_ip_on_mac(dhcps_t *dhcps, u8_t *mac, ip4_addr_t *ip);
/**
* @brief Sets DNS server address for the DHCP server
* @param dhcps Pointer to the DHCP handle
* @param dnsserver Address of the DNS server
* @return ERR_ARG if invalid handle, ERR_OK on success
*/
err_t dhcps_dns_setserver(dhcps_t *dhcps, const ip_addr_t *dnsserver);
/**
* @brief Gets DNS server associated with this DHCP server
* @param dhcps Pointer to the DHCP handle
* @param dnsserver Address of the DNS server
* @return ERR_ARG if invalid handle, ERR_OK on success
*/
err_t dhcps_dns_getserver(dhcps_t *dhcps, ip4_addr_t *dnsserver);
/**
* @brief Sets callback on assigning an IP to the connected client
* @param dhcps Pointer to the DHCP handle
* @param cb Callback for dhcp server
* @param cb_arg Context pointer to be added to the callback
* @return ERR_ARG if invalid handle, ERR_OK on success
*/
err_t dhcps_set_new_lease_cb(dhcps_t *dhcps, dhcps_cb_t cb, void* cb_arg);
#ifdef __cplusplus
}
#endif
#endif /* __DHCPS_H__ */
@@ -0,0 +1,147 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#define ESP_DHCPS 1
#define DHCP_COARSE_TIMER_MSECS 1000
#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 500
#define DHCPS_LEASE_UNIT 1000
#ifdef __cplusplus
extern "C" {
#endif
/** DHCP Options
This macros are not part of the public dhcpserver.h interface.
**/
typedef enum
{
/* RFC 1497 Vendor Extensions */
PAD = 0,
END = 255,
SUBNET_MASK = 1,
TIME_OFFSET = 2,
ROUTER = 3,
TIME_SERVER = 4,
NAME_SERVER = 5,
DOMAIN_NAME_SERVER = 6,
LOG_SERVER = 7,
COOKIE_SERVER = 8,
LPR_SERVER = 9,
IMPRESS_SERVER = 10,
RESOURCE_LOCATION_SERVER = 11,
HOST_NAME = 12,
BOOT_FILE_SIZE = 13,
MERIT_DUMP_FILE = 14,
DOMAIN_NAME = 15,
SWAP_SERVER = 16,
ROOT_PATH = 17,
EXTENSIONS_PATH = 18,
/* IP Layer Parameters per Host */
IP_FORWARDING = 19,
NON_LOCAL_SOURCE_ROUTING = 20,
POLICY_FILTER = 21,
MAXIMUM_DATAGRAM_REASSEMBLY_SIZE = 22,
DEFAULT_IP_TIME_TO_LIVE = 23,
PATH_MTU_AGING_TIMEOUT = 24,
PATH_MTU_PLATEAU_TABLE = 25,
/* IP Layer Parameters per Interface */
INTERFACE_MTU = 26,
ALL_SUBNETS_ARE_LOCAL = 27,
BROADCAST_ADDRESS = 28,
PERFORM_MASK_DISCOVERY = 29,
MASK_SUPPLIER = 30,
PERFORM_ROUTER_DISCOVERY = 31,
ROUTER_SOLICITATION_ADDRESS = 32,
STATIC_ROUTE = 33,
/* Link Layer Parameters per Interface */
TRAILER_ENCAPSULATION = 34,
ARP_CACHE_TIMEOUT = 35,
ETHERNET_ENCAPSULATION = 36,
/* TCP Parameters */
TCP_DEFAULT_TTL = 37,
TCP_KEEPALIVE_INTERVAL = 38,
TCP_KEEPALIVE_GARBAGE = 39,
/* Application and Service Parameters */
NETWORK_INFORMATION_SERVICE_DOMAIN = 40,
NETWORK_INFORMATION_SERVERS = 41,
NETWORK_TIME_PROTOCOL_SERVERS = 42,
VENDOR_SPECIFIC_INFORMATION = 43,
NETBIOS_OVER_TCP_IP_NAME_SERVER = 44,
NETBIOS_OVER_TCP_IP_DATAGRAM_DISTRIBUTION_SERVER = 45,
NETBIOS_OVER_TCP_IP_NODE_TYPE = 46,
NETBIOS_OVER_TCP_IP_SCOPE = 47,
X_WINDOW_SYSTEM_FONT_SERVER = 48,
X_WINDOW_SYSTEM_DISPLAY_MANAGER = 49,
NETWORK_INFORMATION_SERVICE_PLUS_DOMAIN = 64,
NETWORK_INFORMATION_SERVICE_PLUS_SERVERS = 65,
MOBILE_IP_HOME_AGENT = 68,
SMTP_SERVER = 69,
POP3_SERVER = 70,
NNTP_SERVER = 71,
DEFAULT_WWW_SERVER = 72,
DEFAULT_FINGER_SERVER = 73,
DEFAULT_IRC_SERVER = 74,
STREETTALK_SERVER = 75,
STREETTALK_DIRECTORY_ASSISTANCE_SERVER = 76,
/* DHCP Extensions */
REQUESTED_IP_ADDRESS = 50,
IP_ADDRESS_LEASE_TIME = 51,
OPTION_OVERLOAD = 52,
TFTP_SERVER_NAME = 66,
BOOTFILE_NAME = 67,
DHCP_MESSAGE_TYPE = 53,
SERVER_IDENTIFIER = 54,
PARAMETER_REQUEST_LIST = 55,
MESSAGE = 56,
MAXIMUM_DHCP_MESSAGE_SIZE = 57,
RENEWAL_T1_TIME_VALUE = 58,
REBINDING_T2_TIME_VALUE = 59,
VENDOR_CLASS_IDENTIFIER = 60,
CLIENT_IDENTIFIER = 61,
USER_CLASS = 77,
FQDN = 81,
DHCP_AGENT_OPTIONS = 82,
NDS_SERVERS = 85,
NDS_TREE_NAME = 86,
NDS_CONTEXT = 87,
CLIENT_LAST_TRANSACTION_TIME = 91,
ASSOCIATED_IP = 92,
USER_AUTHENTICATION_PROTOCOL = 98,
AUTO_CONFIGURE = 116,
NAME_SERVICE_SEARCH = 117,
SUBNET_SELECTION = 118,
DOMAIN_SEARCH = 119,
CLASSLESS_ROUTE = 121,
} dhcp_msg_option;
#ifdef __cplusplus
}
#endif
+255
View File
@@ -0,0 +1,255 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "lwip/opt.h"
#include "lwip/udp.h"
#include "lwip/mem.h"
#include "dnsproxy.h"
#include "eth_router.h"
#include "eth_queue.h"
static u8_t mdns_payload[DNS_MSG_SIZE];
static struct udp_pcb *pdns_pcb = NULL;
struct ETH_Q dns_q;
static struct NHandle_t tNotifyHandle;
static pthread_t tHandle;
#define MDNS_MAX_NAME_LENGTH (256)
struct __attribute__((__packed__)) mdns_hdr {
u16_t id;
u8_t flags1;
u8_t flags2;
u16_t numquestions;
u16_t numanswers;
u16_t numauthrr;
u16_t numextrarr;
};
#define SIZEOF_DNS_HDR 12
struct __attribute__((__packed__)) mdns_query {
/* MDNS query record starts with either a domain name or a pointer
to a name already present somewhere in the packet. */
u16_t type;
u16_t class;
};
#define SIZEOF_DNS_QUERY 4
struct __attribute__((__packed__)) mdns_answer {
/* MDNS answer record starts with either a domain name or a pointer
to a name already present somewhere in the packet. */
u16_t type;
u16_t class;
u32_t ttl;
u16_t len;
};
#define SIZEOF_DNS_ANSWER 10
struct DNS_RECORD {
uint16_t query_type;
uint16_t query_class;
uint8_t name[512];
uint32_t ip;
uint16_t port;
uint16_t id;
};
static int query_decode(uint8_t* query, int len, struct DNS_RECORD* out) {
int pos=0;
int outpos=0;
do {
if (pos>=len) return -1;
uint8_t nlen=query[pos++];
if (nlen==0) break;
if (outpos+nlen>=sizeof(out->name)-1) return -1;
if (pos+nlen>len) return -1;
for (int i=0; i<nlen; i++) out->name[outpos++]=query[pos++];
out->name[outpos++]='.';
} while(1);
if (pos+4>len) return -1;
if (outpos>0) outpos--;
out->name[outpos]=0;
out->query_type=(query[pos]<<8)+query[pos+1];
out->query_class=(query[pos+2]<<8)+query[pos+3];
return pos+4;
}
static void pdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *iaddr, u16_t port) {
u8_t i;
struct mdns_hdr *hdr;
u8_t nquestions;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(pcb);
struct mdns_info *info = (struct mdns_info *)arg;
/* is the dns message too big ? */
if (p->tot_len > DNS_MSG_SIZE) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
/* free pbuf and return */
goto memerr1;
}
/* is the dns message big enough ? */
if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
/* free pbuf and return */
goto memerr1;
}
/* copy dns payload inside static buffer for processing */
if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) != p->tot_len) goto memerr1;
hdr = (struct mdns_hdr*) mdns_payload;
uint8_t* data=(uint8_t*) mdns_payload + SIZEOF_DNS_HDR;
struct ETH_PBUF* p_req=eth_pbuf_alloc(&xeth_pbuf_ctrl, NULL);
if (p_req==NULL) goto memerr1;
print_log("DNS request: id=%04X fg1=%02X fg2=%02X nq=%d na=%d", htons(hdr->id), hdr->flags1, hdr->flags2, htons(hdr->numquestions), htons(hdr->numanswers));
int num_q=htons(hdr->numquestions);
int num_a=htons(hdr->numanswers);
if (num_a!=0) goto memerr2;
if (num_q!=1) goto memerr2;
int remain_len=p->tot_len-SIZEOF_DNS_HDR;
struct DNS_RECORD* rec=(struct DNS_RECORD*)p_req->pbuf.payload;
int len=query_decode(data, remain_len, rec);
if (len<0) goto memerr2;
rec->id=htons(hdr->id);
rec->ip=*(uint32_t*)iaddr;
rec->port=port;
print_log("DNS request: <%s> from ip=%d.%d.%d.%d port=%d", rec->name, (rec->ip)&0xff, (rec->ip>>8)&0xff, (rec->ip>>16)&0xff, (rec->ip>>24)&0xff, rec->port);
add_to_custom_queue(&p_req->pbuf, &dns_q);
TNotifyAdd( &tNotifyHandle, 1);
goto memerr1;
memerr2:
eth_pbuf_free_request(p_req);
memerr1:
pbuf_free(p);
return;
}
// a a a . b b b . c c c 0
// 3 a a a 3 b b b 3 c c c 0
// 0 1 2 3 4 5 6 7 8 9 B C D
int dns_encode_name(uint8_t* dst, uint8_t* str) {
int pos=0;
int cnt=0;
do {
if (str[pos]=='.') { dst[pos-cnt]=cnt; cnt=0; pos++; continue;}
if (str[pos]==0) { dst[pos-cnt]=cnt; dst[pos+1]=0; pos+=2; break; }
dst[pos+1]=str[pos];
pos++; cnt++;
} while(1);
return pos;
}
_Noreturn void dnsproxy_thread(void* arg) {
struct pbuf* p;
while (1) {
uint32_t res=TNotifyWait( &tNotifyHandle );
do {
p=get_from_custom_queue(&dns_q);
if (p==NULL) break;
struct DNS_RECORD* rec=(struct DNS_RECORD*)p->payload;
int status;
struct addrinfo hints;
struct addrinfo *servinfo; // указатель на результаты
memset(&hints, 0, sizeof hints); // убедимся, что структура пуста
hints.ai_family = PF_INET;//AF_UNSPEC - AF_INET; // неважно, IPv4 или IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream-sockets
hints.ai_flags = AI_PASSIVE; // заполните мой IP-адрес за меняif ((status = getaddrinfo(NULL, «3490», &hints, &servinfo)) != 0) {
status = getaddrinfo(rec->name, NULL, &hints, &servinfo);// servinfo теперь —
if (status==0 && servinfo->ai_family==AF_INET) {
uint8_t* ip=(uint8_t*)&((struct sockaddr_in *)servinfo->ai_addr)->sin_addr;
print_log("DNS query service: <%s> IP=%d.%d.%d.%d", rec->name, ip[0], ip[1], ip[2], ip[3]);
struct pbuf* p1 = pbuf_alloc(PBUF_TRANSPORT, 1400, PBUF_RAM);
if (p1 != NULL) {
int pos=0;
struct mdns_hdr* hdr=p1->payload;
hdr->id=htons(rec->id);
hdr->flags1=0x81;
hdr->flags2=0x80;
// FLAGS1 FLAGS2 Flags: 0x8180 Standard query response, No error
// 1... .... .... .... = Response: Message is a response
// .000 0... .... .... = Opcode: Standard query (0)
// .... .0.. .... .... = Authoritative: Server is not an authority for domain
// .... ..0. .... .... = Truncated: Message is not truncated
// .... ...1 .... .... = Recursion desired: Do query recursively
// .... .... 1... .... = Recursion available: Server can do recursive queries
// .... .... .0.. .... = Z: reserved (0)
// .... .... ..0. .... = Answer authenticated: Answer/authority portion was not authenticated by the server
// .... .... ...0 .... = Non-authenticated data: Unacceptable
// .... .... .... 0000 = Reply code: No error (0)
hdr->numquestions=htons(1);
hdr->numanswers=htons(1);
hdr->numauthrr=htons(0);
hdr->numextrarr=htons(0);
uint8_t dpos=sizeof(struct mdns_hdr);
uint8_t* rsp=(uint8_t*)p1->payload;
int ret=dns_encode_name(rsp+dpos, rec->name);
if (ret>0) {
dpos += ret;
rsp[dpos++]=0;// TYPE
rsp[dpos++]=1;
rsp[dpos++]=0;// CLASS
rsp[dpos++]=1;
rsp[dpos++]=0xc0;// answer: name
rsp[dpos++]=0x0c;
rsp[dpos++]=0;// type
rsp[dpos++]=1;
rsp[dpos++]=0;// class
rsp[dpos++]=1;
rsp[dpos++]=0;// TTL
rsp[dpos++]=0;// TTL
rsp[dpos++]=0x27;// TTL
rsp[dpos++]=0x10;// TTL
rsp[dpos++]=0;// data length
rsp[dpos++]=4;// data length
rsp[dpos++]=ip[0];
rsp[dpos++]=ip[1];
rsp[dpos++]=ip[2];
rsp[dpos++]=ip[3];
p1->len=dpos;
p1->tot_len=dpos;
char ans[3000]; int pt=0;
for (int i=0; i<dpos; i++) {pt+=sprintf(ans+pt,"%02X ",rsp[i]);}
print_log("DNS answer: <%s>", ans);
udp_sendto(pdns_pcb, p1, &rec->ip, rec->port);
}
pbuf_free(p1);
}
} else print_log("DNS query err (status=%d)", status);
pbuf_free(p);
} while(1);
}
}
void dnsproxy_init() {
dns_q.q_len_max=5;
int ret;
pdns_pcb = udp_new();
if (pdns_pcb) {
ret=udp_bind(pdns_pcb, IP_ADDR_ANY, 53);
if (ret) return;
udp_recv(pdns_pcb, pdns_recv, NULL);
}
TaskCreate (dnsproxy_thread, &tHandle);
TNotifyCreate(&tNotifyHandle);
}
+3
View File
@@ -0,0 +1,3 @@
#define DNS_MSG_SIZE 1500
void dnsproxy_init();
@@ -0,0 +1,150 @@
// LWIP interface for router
#include <string.h>
#include "lwip/lwip.h"
#include "lwip/opt.h"
#include "lwip/timeouts.h"
#include "netif/ethernet.h"
#include "netif/etharp.h"
#include "lwip/tcpip.h"
#include "lwip/pbuf.h"
#include "eth_mem.h"
#include "eth_router_cfg.h"
#include "eth_router.h"
#include "lwip/eth_router_if_lwip.h"
static struct ETH_QUEUEPOOL_CTRL* if_pool=&xeth_queuepool_ctrl;
struct netif* lwip_netif;
static pthread_t xLWIP_input_task;
static pthread_t xLWIP_tmr_task;
struct NHandle_t TTskHandle;
struct ETH_IF_LWIP_STATS eth_if_lwip;
static char if_name[]="LWIP";
struct ETH_PBUF* block_to_send;
//#pragma optimize=none
static err_t lwip_output_to_bridge(struct netif *netif, struct pbuf *p) {
if (p->tot_len>ETH_MEM_BUF_SIZE) {
eth_if_lwip.in_too_big++;
return ERR_OK;
}
struct ETH_PBUF* block=eth_pbuf_alloc(&xeth_pbuf_ctrl, NULL);
if (block==NULL) {
eth_if_lwip.in_alloc_errs++;
return ERR_OK;
}
int ptr=0;
struct pbuf *frag;
for (frag=p; frag!=NULL; frag=frag->next) {// copy datagram payload from LWIP to ETH_MEM pbuf
if (frag->len+ptr<=ETH_MEM_BUF_SIZE) memcpy((uint8_t*)block->pbuf.payload+ptr, frag->payload, frag->len);
else {
eth_pbuf_free_request(block);
eth_if_lwip.in_too_big++;
return ERR_OK;
}
ptr+=frag->len;
}
// print_log("dgram from LWIP, size=%d",ptr);
block->pbuf.len=ptr;
block->pbuf.tot_len=ptr;
block->pbuf.if_idx=LWIP_NETIF_ID;
for (int i=0; i<6; i++) ((uint8_t*)(block->pbuf.payload))[i+6]=netif->hwaddr[i];
eth_add_packet_to_router_queue(block);
return ERR_OK;
}
static void to_lwip_QueueTask(void* arg) {
print_log("********** LWIP task started");
while (1) {
int res=TNotifyWait( &TTskHandle );
if (res & 2) {
LOCK_LWIP_CORE();
sys_check_timeouts();
UNLOCK_LWIP_CORE();
}
if (res & 1) do {
if (block_to_send->pbuf.ref==0) while(1);
int in=0;
int err=1;
LOCK_LWIP_CORE();
if (lwip_netif->input) err=lwip_netif->input(&block_to_send->pbuf, lwip_netif);
UNLOCK_LWIP_CORE();
// if (err == ERR_OK) in=1;
// print_log("dgram to LWIP, size=%d",block_to_send->pbuf.len);
if (err != ERR_OK) eth_pbuf_free_request(block_to_send);
// if (in==0) {
// eth_if_lwip.lwip_out_errs++; eth_if_lwip.lwip_out_err=err;
// LOCK_LWIP_CORE();
// if (lwip_netif->input) err=lwip_netif->input(&block_to_send->pbuf, lwip_netif);
// UNLOCK_LWIP_CORE();
// if (err) eth_pbuf_free_request(block_to_send);
// }
block_to_send=NULL;
struct ETH_PBUF* tb=eth_get_packet(&if_pool->eth_netif_array[LWIP_NETIF_ID]);
if (tb) block_to_send=tb;
} while (block_to_send);
}
}
static void to_lwip_TmrTask(void* arg) {
while(1) {
TNotifyAdd( &TTskHandle, 2);
usleep(1000*100);
}
}
static void lwip_callback_from_bridge(struct ETH_PBUF* block, struct ETH_NETIF* enetif) {
block_to_send=block;
TNotifyAdd( &TTskHandle, 1);
}
err_t eth_lwip_if_init(struct netif *netif) {
LWIP_ASSERT("netif != NULL", (netif != NULL));
lwip_netif=netif;
netif->name[0] = 'L';
netif->name[1] = 'W';
print_log("********** LWIP interface init");
netif->output = etharp_output;
netif->linkoutput = lwip_output_to_bridge;//low_level_output;
for (int i=0; i<6; i++) netif->hwaddr[i] = rand();
netif->hwaddr[0]=0x00;
netif->hwaddr[1]=0x80;
netif->hwaddr_len = ETH_HWADDR_LEN;
netif->mtu = 1500;//ETH_MAX_PAYLOAD;
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
if (xLWIP_input_task==NULL) {
if_pool->eth_netif_array[LWIP_NETIF_ID].callback_fn=lwip_callback_from_bridge;
TaskCreate (to_lwip_QueueTask, &xLWIP_input_task);
TaskCreate (to_lwip_TmrTask, &xLWIP_tmr_task);
TNotifyCreate(&TTskHandle);
while ( eth_get_packet(&if_pool->eth_netif_array[LWIP_NETIF_ID]) );
}
if_pool->eth_netif_array[LWIP_NETIF_ID].q_output_len_max=LWIP_NETIF_QLEN;
if_pool->eth_netif_array[LWIP_NETIF_ID].if_name=if_name;
netif_set_up(netif);
netif_set_link_up(netif);
if_pool->eth_netif_array[LWIP_NETIF_ID].if_up=1;
return ERR_OK;
}
@@ -0,0 +1,13 @@
#define LWIP_TASK_STACK_SIZE 1024// x4 bytes
err_t eth_lwip_if_init(struct netif *netif);
extern struct netif* lwip_netif;
struct ETH_IF_LWIP_STATS {
uint32_t in_frags;
uint32_t in_too_big;
uint32_t in_alloc_errs;
uint32_t lwip_out_errs;
err_enum_t lwip_out_err;
};
extern struct ETH_IF_LWIP_STATS eth_if_lwip;
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_ARCH_CC_H
#define LWIP_ARCH_CC_H
/* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */
#if defined __ANDROID__
#define LWIP_UNIX_ANDROID
#elif defined __linux__
#define LWIP_UNIX_LINUX
#elif defined __APPLE__
#define LWIP_UNIX_MACH
#elif defined __OpenBSD__
#define LWIP_UNIX_OPENBSD
#elif defined __CYGWIN__
#define LWIP_UNIX_CYGWIN
#elif defined __GNU__
#define LWIP_UNIX_HURD
#endif
#define LWIP_TIMEVAL_PRIVATE 0
#include <sys/time.h>
#define LWIP_ERRNO_INCLUDE <errno.h>
#if defined(LWIP_UNIX_LINUX) || defined(LWIP_UNIX_HURD)
#define LWIP_ERRNO_STDINCLUDE 1
#endif
//extern unsigned int lwip_port_rand(void);
#define LWIP_RAND() (rand())
/* different handling for unit test, normally not needed */
#ifdef LWIP_NOASSERT_ON_ERROR
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
handler;}} while(0)
#endif
#if defined(LWIP_UNIX_ANDROID) && defined(FD_SET)
//typedef __kernel_fd_set fd_set;
#endif
#if defined(LWIP_UNIX_MACH)
/* sys/types.h and signal.h bring in Darwin byte order macros. pull the
header here and disable LwIP's version so that apps still can get
the macros via LwIP headers and use system headers */
#include <sys/types.h>
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
#endif
struct sio_status_s;
typedef struct sio_status_s sio_status_t;
#define sio_fd_t sio_status_t*
#define __sio_fd_t_defined
typedef unsigned int sys_prot_t;
#endif /* LWIP_ARCH_CC_H */
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_ARCH_PERF_H
#define LWIP_ARCH_PERF_H
#include <sys/times.h>
#ifdef PERF
#define PERF_START { \
unsigned long __c1l, __c1h, __c2l, __c2h; \
__asm__(".byte 0x0f, 0x31" : "=a" (__c1l), "=d" (__c1h))
#define PERF_STOP(x) __asm__(".byte 0x0f, 0x31" : "=a" (__c2l), "=d" (__c2h)); \
perf_print(__c1l, __c1h, __c2l, __c2h, x);}
/*#define PERF_START do { \
struct tms __perf_start, __perf_end; \
times(&__perf_start)
#define PERF_STOP(x) times(&__perf_end); \
perf_print_times(&__perf_start, &__perf_end, x);\
} while(0)*/
#else /* PERF */
#define PERF_START /* null definition */
#define PERF_STOP(x) /* null definition */
#endif /* PERF */
void perf_print(unsigned long c1l, unsigned long c1h,
unsigned long c2l, unsigned long c2h,
char *key);
void perf_print_times(struct tms *start, struct tms *end, char *key);
void perf_init(char *fname);
#endif /* LWIP_ARCH_PERF_H */
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_ARCH_SYS_ARCH_H
#define LWIP_ARCH_SYS_ARCH_H
#define SYS_MBOX_NULL NULL
#define SYS_SEM_NULL NULL
/*typedef u32_t sys_prot_t;*/
struct sys_sem;
typedef struct sys_sem * sys_sem_t;
#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL))
#define sys_sem_valid_val(sem) ((sem) != NULL)
#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0)
#define sys_sem_set_invalid_val(sem) do { (sem) = NULL; }while(0)
struct sys_mutex;
typedef struct sys_mutex * sys_mutex_t;
#define sys_mutex_valid(mutex) sys_sem_valid(mutex)
#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex)
struct sys_mbox;
typedef struct sys_mbox * sys_mbox_t;
#define sys_mbox_valid(mbox) sys_sem_valid(mbox)
#define sys_mbox_valid_val(mbox) sys_sem_valid_val(mbox)
#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox)
#define sys_mbox_set_invalid_val(mbox) sys_sem_set_invalid_val(mbox)
struct sys_thread;
typedef struct sys_thread * sys_thread_t;
#define LWIP_EXAMPLE_APP_ABORT() lwip_unix_keypressed()
int lwip_unix_keypressed(void);
#endif /* LWIP_ARCH_SYS_ARCH_H */
@@ -0,0 +1,201 @@
/**
* @file
* Application layered TCP connection API (to be used from TCPIP thread)\n
*
* This file contains the generic API.
* For more details see @ref altcp_api.
*/
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_ALTCP_H
#define LWIP_HDR_ALTCP_H
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#include "lwip/tcpbase.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#ifdef __cplusplus
extern "C" {
#endif
struct altcp_pcb;
struct altcp_functions;
typedef err_t (*altcp_accept_fn)(void *arg, struct altcp_pcb *new_conn, err_t err);
typedef err_t (*altcp_connected_fn)(void *arg, struct altcp_pcb *conn, err_t err);
typedef err_t (*altcp_recv_fn)(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err);
typedef err_t (*altcp_sent_fn)(void *arg, struct altcp_pcb *conn, u16_t len);
typedef err_t (*altcp_poll_fn)(void *arg, struct altcp_pcb *conn);
typedef void (*altcp_err_fn)(void *arg, err_t err);
typedef struct altcp_pcb* (*altcp_new_fn)(void *arg, u8_t ip_type);
struct altcp_pcb {
const struct altcp_functions *fns;
struct altcp_pcb *inner_conn;
void *arg;
void *state;
/* application callbacks */
altcp_accept_fn accept;
altcp_connected_fn connected;
altcp_recv_fn recv;
altcp_sent_fn sent;
altcp_poll_fn poll;
altcp_err_fn err;
u8_t pollinterval;
};
/** @ingroup altcp */
typedef struct altcp_allocator_s {
/** Allocator function */
altcp_new_fn alloc;
/** Argument to allocator function */
void *arg;
} altcp_allocator_t;
struct altcp_pcb *altcp_new(altcp_allocator_t *allocator);
struct altcp_pcb *altcp_new_ip6(altcp_allocator_t *allocator);
struct altcp_pcb *altcp_new_ip_type(altcp_allocator_t *allocator, u8_t ip_type);
void altcp_arg(struct altcp_pcb *conn, void *arg);
void altcp_accept(struct altcp_pcb *conn, altcp_accept_fn accept);
void altcp_recv(struct altcp_pcb *conn, altcp_recv_fn recv);
void altcp_sent(struct altcp_pcb *conn, altcp_sent_fn sent);
void altcp_poll(struct altcp_pcb *conn, altcp_poll_fn poll, u8_t interval);
void altcp_err(struct altcp_pcb *conn, altcp_err_fn err);
void altcp_recved(struct altcp_pcb *conn, u16_t len);
err_t altcp_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port);
err_t altcp_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected);
/* return conn for source code compatibility to tcp callback API only */
struct altcp_pcb *altcp_listen_with_backlog_and_err(struct altcp_pcb *conn, u8_t backlog, err_t *err);
#define altcp_listen_with_backlog(conn, backlog) altcp_listen_with_backlog_and_err(conn, backlog, NULL)
/** @ingroup altcp */
#define altcp_listen(conn) altcp_listen_with_backlog_and_err(conn, TCP_DEFAULT_LISTEN_BACKLOG, NULL)
void altcp_abort(struct altcp_pcb *conn);
err_t altcp_close(struct altcp_pcb *conn);
err_t altcp_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx);
err_t altcp_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags);
err_t altcp_output(struct altcp_pcb *conn);
u16_t altcp_mss(struct altcp_pcb *conn);
u16_t altcp_sndbuf(struct altcp_pcb *conn);
u16_t altcp_sndqueuelen(struct altcp_pcb *conn);
void altcp_nagle_disable(struct altcp_pcb *conn);
void altcp_nagle_enable(struct altcp_pcb *conn);
int altcp_nagle_disabled(struct altcp_pcb *conn);
void altcp_setprio(struct altcp_pcb *conn, u8_t prio);
err_t altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port);
ip_addr_t *altcp_get_ip(struct altcp_pcb *conn, int local);
u16_t altcp_get_port(struct altcp_pcb *conn, int local);
#ifdef LWIP_DEBUG
enum tcp_state altcp_dbg_get_tcp_state(struct altcp_pcb *conn);
#endif
#ifdef __cplusplus
}
#endif
#else /* LWIP_ALTCP */
/* ALTCP disabled, define everything to link against tcp callback API (e.g. to get a small non-ssl httpd) */
#include "lwip/tcp.h"
#define altcp_accept_fn tcp_accept_fn
#define altcp_connected_fn tcp_connected_fn
#define altcp_recv_fn tcp_recv_fn
#define altcp_sent_fn tcp_sent_fn
#define altcp_poll_fn tcp_poll_fn
#define altcp_err_fn tcp_err_fn
#define altcp_pcb tcp_pcb
#define altcp_tcp_new_ip_type tcp_new_ip_type
#define altcp_tcp_new tcp_new
#define altcp_tcp_new_ip6 tcp_new_ip6
#define altcp_new(allocator) tcp_new()
#define altcp_new_ip6(allocator) tcp_new_ip6()
#define altcp_new_ip_type(allocator, ip_type) tcp_new_ip_type(ip_type)
#define altcp_arg tcp_arg
#define altcp_accept tcp_accept
#define altcp_recv tcp_recv
#define altcp_sent tcp_sent
#define altcp_poll tcp_poll
#define altcp_err tcp_err
#define altcp_recved tcp_recved
#define altcp_bind tcp_bind
#define altcp_connect tcp_connect
#define altcp_listen_with_backlog_and_err tcp_listen_with_backlog_and_err
#define altcp_listen_with_backlog tcp_listen_with_backlog
#define altcp_listen tcp_listen
#define altcp_abort tcp_abort
#define altcp_close tcp_close
#define altcp_shutdown tcp_shutdown
#define altcp_write tcp_write
#define altcp_output tcp_output
#define altcp_mss tcp_mss
#define altcp_sndbuf tcp_sndbuf
#define altcp_sndqueuelen tcp_sndqueuelen
#define altcp_nagle_disable tcp_nagle_disable
#define altcp_nagle_enable tcp_nagle_enable
#define altcp_nagle_disabled tcp_nagle_disabled
#define altcp_setprio tcp_setprio
#define altcp_get_tcp_addrinfo tcp_get_tcp_addrinfo
#define altcp_get_ip(pcb, local) ((local) ? (&(pcb)->local_ip) : (&(pcb)->remote_ip))
#ifdef LWIP_DEBUG
#define altcp_dbg_get_tcp_state tcp_dbg_get_tcp_state
#endif
#endif /* LWIP_ALTCP */
#endif /* LWIP_HDR_ALTCP_H */
@@ -0,0 +1,72 @@
/**
* @file
* Application layered TCP connection API (to be used from TCPIP thread)\n
* This interface mimics the tcp callback API to the application while preventing
* direct linking (much like virtual functions).
* This way, an application can make use of other application layer protocols
* on top of TCP without knowing the details (e.g. TLS, proxy connection).
*
* This file contains the base implementation calling into tcp.
*/
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_ALTCP_TCP_H
#define LWIP_HDR_ALTCP_TCP_H
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#include "lwip/altcp.h"
#ifdef __cplusplus
extern "C" {
#endif
struct altcp_pcb *altcp_tcp_new_ip_type(u8_t ip_type);
#define altcp_tcp_new() altcp_tcp_new_ip_type(IPADDR_TYPE_V4)
#define altcp_tcp_new_ip6() altcp_tcp_new_ip_type(IPADDR_TYPE_V6)
struct altcp_pcb *altcp_tcp_alloc(void *arg, u8_t ip_type);
struct tcp_pcb;
struct altcp_pcb *altcp_tcp_wrap(struct tcp_pcb *tpcb);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_ALTCP */
#endif /* LWIP_HDR_ALTCP_TCP_H */
@@ -0,0 +1,117 @@
/**
* @file
* Application layered TCP/TLS connection API (to be used from TCPIP thread)
*
* @defgroup altcp_tls TLS layer
* @ingroup altcp
* This file contains function prototypes for a TLS layer.
* A port to ARM mbedtls is provided in the apps/ tree
* (LWIP_ALTCP_TLS_MBEDTLS option).
*/
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_ALTCP_TLS_H
#define LWIP_HDR_ALTCP_TLS_H
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#if LWIP_ALTCP_TLS
#include "lwip/altcp.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @ingroup altcp_tls
* ALTCP_TLS configuration handle, content depends on port (e.g. mbedtls)
*/
struct altcp_tls_config;
/** @ingroup altcp_tls
* Create an ALTCP_TLS server configuration handle
*/
struct altcp_tls_config *altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
const u8_t *privkey_pass, size_t privkey_pass_len,
const u8_t *cert, size_t cert_len);
/** @ingroup altcp_tls
* Create an ALTCP_TLS client configuration handle
*/
struct altcp_tls_config *altcp_tls_create_config_client(const u8_t *cert, size_t cert_len);
/** @ingroup altcp_tls
* Create an ALTCP_TLS client configuration handle with two-way server/client authentication
*/
struct altcp_tls_config *altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len,
const u8_t *privkey_pass, size_t privkey_pass_len,
const u8_t *cert, size_t cert_len);
/** @ingroup altcp_tls
* Free an ALTCP_TLS configuration handle
*/
void altcp_tls_free_config(struct altcp_tls_config *conf);
/** @ingroup altcp_tls
* Create new ALTCP_TLS layer wrapping an existing pcb as inner connection (e.g. TLS over TCP)
*/
struct altcp_pcb *altcp_tls_wrap(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb);
/** @ingroup altcp_tls
* Create new ALTCP_TLS pcb and its inner tcp pcb
*/
struct altcp_pcb *altcp_tls_new(struct altcp_tls_config *config, u8_t ip_type);
/** @ingroup altcp_tls
* Create new ALTCP_TLS layer pcb and its inner tcp pcb.
* Same as @ref altcp_tls_new but this allocator function fits to
* @ref altcp_allocator_t / @ref altcp_new.\n
'arg' must contain a struct altcp_tls_config *.
*/
struct altcp_pcb *altcp_tls_alloc(void *arg, u8_t ip_type);
/** @ingroup altcp_tls
* Return pointer to internal TLS context so application can tweak it.
* Real type depends on port (e.g. mbedtls)
*/
void *altcp_tls_context(struct altcp_pcb *conn);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_ALTCP_TLS */
#endif /* LWIP_ALTCP */
#endif /* LWIP_HDR_ALTCP_TLS_H */
@@ -0,0 +1,431 @@
/**
* @file
* netconn API (to be used from non-TCPIP threads)
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_API_H
#define LWIP_HDR_API_H
#include "lwip/opt.h"
#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
/* Note: Netconn API is always available when sockets are enabled -
* sockets are implemented on top of them */
#include "lwip/arch.h"
#include "lwip/netbuf.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Throughout this file, IP addresses and port numbers are expected to be in
* the same byte order as in the corresponding pcb.
*/
/* Flags for netconn_write (u8_t) */
#define NETCONN_NOFLAG 0x00
#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */
#define NETCONN_COPY 0x01
#define NETCONN_MORE 0x02
#define NETCONN_DONTBLOCK 0x04
#define NETCONN_NOAUTORCVD 0x08 /* prevent netconn_recv_data_tcp() from updating the tcp window - must be done manually via netconn_tcp_recvd() */
#define NETCONN_NOFIN 0x10 /* upper layer already received data, leave FIN in queue until called again */
/* Flags for struct netconn.flags (u8_t) */
/** This netconn had an error, don't block on recvmbox/acceptmbox any more */
#define NETCONN_FLAG_MBOXCLOSED 0x01
/** Should this netconn avoid blocking? */
#define NETCONN_FLAG_NON_BLOCKING 0x02
/** Was the last connect action a non-blocking one? */
#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04
#if LWIP_NETCONN_FULLDUPLEX
/** The mbox of this netconn is being deallocated, don't use it anymore */
#define NETCONN_FLAG_MBOXINVALID 0x08
#endif /* LWIP_NETCONN_FULLDUPLEX */
/** If a nonblocking write has been rejected before, poll_tcp needs to
check if the netconn is writable again */
#define NETCONN_FLAG_CHECK_WRITESPACE 0x10
#if LWIP_IPV6
/** If this flag is set then only IPv6 communication is allowed on the
netconn. As per RFC#3493 this features defaults to OFF allowing
dual-stack usage by default. */
#define NETCONN_FLAG_IPV6_V6ONLY 0x20
#endif /* LWIP_IPV6 */
#if LWIP_NETBUF_RECVINFO
/** Received packet info will be recorded for this netconn */
#define NETCONN_FLAG_PKTINFO 0x40
#endif /* LWIP_NETBUF_RECVINFO */
/** A FIN has been received but not passed to the application yet */
#define NETCONN_FIN_RX_PENDING 0x80
/* Helpers to process several netconn_types by the same code */
#define NETCONNTYPE_GROUP(t) ((t)&0xF0)
#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0)
#if LWIP_IPV6
#define NETCONN_TYPE_IPV6 0x08
#define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0)
#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE)
#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM)
#else /* LWIP_IPV6 */
#define NETCONNTYPE_ISIPV6(t) (0)
#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE)
#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM)
#endif /* LWIP_IPV6 */
/** @ingroup netconn_common
* Protocol family and type of the netconn
*/
enum netconn_type {
NETCONN_INVALID = 0,
/** TCP IPv4 */
NETCONN_TCP = 0x10,
#if LWIP_IPV6
/** TCP IPv6 */
NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */,
#endif /* LWIP_IPV6 */
/** UDP IPv4 */
NETCONN_UDP = 0x20,
/** UDP IPv4 lite */
NETCONN_UDPLITE = 0x21,
/** UDP IPv4 no checksum */
NETCONN_UDPNOCHKSUM = 0x22,
#if LWIP_IPV6
/** UDP IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */,
/** UDP IPv6 lite (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */,
/** UDP IPv6 no checksum (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */,
#endif /* LWIP_IPV6 */
/** Raw connection IPv4 */
NETCONN_RAW = 0x40
#if LWIP_IPV6
/** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
, NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */
#endif /* LWIP_IPV6 */
};
/** Current state of the netconn. Non-TCP netconns are always
* in state NETCONN_NONE! */
enum netconn_state {
NETCONN_NONE,
NETCONN_WRITE,
NETCONN_LISTEN,
NETCONN_CONNECT,
NETCONN_CLOSE
};
/** Used to inform the callback function about changes
*
* Event explanation:
*
* In the netconn implementation, there are three ways to block a client:
*
* - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept())
* - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data())
* - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write())
*
* The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking
* connections, you need to know in advance whether a call to a netconn function call would block or not,
* and these events tell you about that.
*
* RCVPLUS events say: Safe to perform a potentially blocking call call once more.
* They are counted in sockets - three RCVPLUS events for accept mbox means you are safe
* to call netconn_accept 3 times without being blocked.
* Same thing for receive mbox.
*
* RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged".
* Socket implementation decrements the counter.
*
* For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something.
* SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again.
* A SENDMINUS event occurs when the next call to a netconn_send() would be blocking.
*/
enum netconn_evt {
NETCONN_EVT_RCVPLUS,
NETCONN_EVT_RCVMINUS,
NETCONN_EVT_SENDPLUS,
NETCONN_EVT_SENDMINUS,
NETCONN_EVT_ERROR
};
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
/** Used for netconn_join_leave_group() */
enum netconn_igmp {
NETCONN_JOIN,
NETCONN_LEAVE
};
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
#if LWIP_DNS
/* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */
#define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6
#define NETCONN_DNS_IPV4 0
#define NETCONN_DNS_IPV6 1
#define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */
#define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */
#endif /* LWIP_DNS */
/* forward-declare some structs to avoid to include their headers */
struct ip_pcb;
struct tcp_pcb;
struct udp_pcb;
struct raw_pcb;
struct netconn;
struct api_msg;
/** A callback prototype to inform about events for a netconn */
typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len);
/** A netconn descriptor */
struct netconn {
/** type of the netconn (TCP, UDP or RAW) */
enum netconn_type type;
/** current state of the netconn */
enum netconn_state state;
/** the lwIP internal protocol control block */
union {
struct ip_pcb *ip;
struct tcp_pcb *tcp;
struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb;
/** the last asynchronous unreported error this netconn had */
err_t pending_err;
#if !LWIP_NETCONN_SEM_PER_THREAD
/** sem that is used to synchronously execute functions in the core context */
sys_sem_t op_completed;
#endif
/** mbox where received packets are stored until they are fetched
by the netconn application thread (can grow quite big) */
sys_mbox_t recvmbox;
#if LWIP_TCP
/** mbox where new connections are stored until processed
by the application thread */
sys_mbox_t acceptmbox;
#endif /* LWIP_TCP */
#if LWIP_NETCONN_FULLDUPLEX
/** number of threads waiting on an mbox. This is required to unblock
all threads when closing while threads are waiting. */
int mbox_threads_waiting;
#endif
/** only used for socket layer */
#if LWIP_SOCKET
int socket;
#endif /* LWIP_SOCKET */
#if LWIP_SO_SNDTIMEO
/** timeout to wait for sending data (which means enqueueing data for sending
in internal buffers) in milliseconds */
s32_t send_timeout;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVTIMEO
/** timeout in milliseconds to wait for new data to be received
(or connections to arrive for listening netconns) */
u32_t recv_timeout;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
/** maximum amount of bytes queued in recvmbox
not used for TCP: adjust TCP_WND instead! */
int recv_bufsize;
/** number of bytes currently in recvmbox to be received,
tested against recv_bufsize to limit bytes on recvmbox
for UDP and RAW, used for FIONREAD */
int recv_avail;
#endif /* LWIP_SO_RCVBUF */
#if LWIP_SO_LINGER
/** values <0 mean linger is disabled, values > 0 are seconds to linger */
s16_t linger;
#endif /* LWIP_SO_LINGER */
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
u8_t flags;
#if LWIP_TCP
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
this temporarily stores the message.
Also used during connect and close. */
struct api_msg *current_msg;
#endif /* LWIP_TCP */
/** A callback function that is informed about events for this netconn */
netconn_callback callback;
};
/** This vector type is passed to @ref netconn_write_vectors_partly to send
* multiple buffers at once.
* ATTENTION: This type has to directly map struct iovec since one is casted
* into the other!
*/
struct netvector {
/** pointer to the application buffer that contains the data to send */
const void *ptr;
/** size of the application data to send */
size_t len;
};
/** Register an Network connection event */
#define API_EVENT(c,e,l) if (c->callback) { \
(*c->callback)(c, e, l); \
}
/* Network connection functions: */
/** @ingroup netconn_common
* Create new netconn connection
* @param t @ref netconn_type */
#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL)
#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c)
struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
netconn_callback callback);
err_t netconn_prepare_delete(struct netconn *conn);
err_t netconn_delete(struct netconn *conn);
/** Get the type of a netconn (as enum netconn_type). */
#define netconn_type(conn) (conn->type)
err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr,
u16_t *port, u8_t local);
/** @ingroup netconn_common */
#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0)
/** @ingroup netconn_common */
#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1)
err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port);
err_t netconn_bind_if(struct netconn *conn, u8_t if_idx);
err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port);
err_t netconn_disconnect (struct netconn *conn);
err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog);
/** @ingroup netconn_tcp */
#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG)
err_t netconn_accept(struct netconn *conn, struct netconn **new_conn);
err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf);
err_t netconn_recv_udp_raw_netbuf(struct netconn *conn, struct netbuf **new_buf);
err_t netconn_recv_udp_raw_netbuf_flags(struct netconn *conn, struct netbuf **new_buf, u8_t apiflags);
err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf);
err_t netconn_recv_tcp_pbuf_flags(struct netconn *conn, struct pbuf **new_buf, u8_t apiflags);
err_t netconn_tcp_recvd(struct netconn *conn, size_t len);
err_t netconn_sendto(struct netconn *conn, struct netbuf *buf,
const ip_addr_t *addr, u16_t port);
err_t netconn_send(struct netconn *conn, struct netbuf *buf);
err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
u8_t apiflags, size_t *bytes_written);
err_t netconn_write_vectors_partly(struct netconn *conn, struct netvector *vectors, u16_t vectorcnt,
u8_t apiflags, size_t *bytes_written);
/** @ingroup netconn_tcp */
#define netconn_write(conn, dataptr, size, apiflags) \
netconn_write_partly(conn, dataptr, size, apiflags, NULL)
err_t netconn_close(struct netconn *conn);
err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr,
const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
err_t netconn_join_leave_group_netif(struct netconn *conn, const ip_addr_t *multiaddr,
u8_t if_idx, enum netconn_igmp join_or_leave);
#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
#if LWIP_DNS
#if LWIP_IPV4 && LWIP_IPV6
err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype);
#define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT)
#else /* LWIP_IPV4 && LWIP_IPV6 */
err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
#define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr)
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#endif /* LWIP_DNS */
err_t netconn_err(struct netconn *conn);
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
#define netconn_set_flags(conn, set_flags) do { (conn)->flags = (u8_t)((conn)->flags | (set_flags)); } while(0)
#define netconn_clear_flags(conn, clr_flags) do { (conn)->flags = (u8_t)((conn)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0)
#define netconn_is_flag_set(conn, flag) (((conn)->flags & (flag)) != 0)
/** Set the blocking status of netconn calls (@todo: write/send is missing) */
#define netconn_set_nonblocking(conn, val) do { if(val) { \
netconn_set_flags(conn, NETCONN_FLAG_NON_BLOCKING); \
} else { \
netconn_clear_flags(conn, NETCONN_FLAG_NON_BLOCKING); }} while(0)
/** Get the blocking status of netconn calls (@todo: write/send is missing) */
#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0)
#if LWIP_IPV6
/** @ingroup netconn_common
* TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY)
*/
#define netconn_set_ipv6only(conn, val) do { if(val) { \
netconn_set_flags(conn, NETCONN_FLAG_IPV6_V6ONLY); \
} else { \
netconn_clear_flags(conn, NETCONN_FLAG_IPV6_V6ONLY); }} while(0)
/** @ingroup netconn_common
* TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY)
*/
#define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0)
#endif /* LWIP_IPV6 */
#if LWIP_SO_SNDTIMEO
/** Set the send timeout in milliseconds */
#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout))
/** Get the send timeout in milliseconds */
#define netconn_get_sendtimeout(conn) ((conn)->send_timeout)
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO
/** Set the receive timeout in milliseconds */
#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout))
/** Get the receive timeout in milliseconds */
#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout)
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
/** Set the receive buffer in bytes */
#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize))
/** Get the receive buffer in bytes */
#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize)
#endif /* LWIP_SO_RCVBUF*/
#if LWIP_NETCONN_SEM_PER_THREAD
void netconn_thread_init(void);
void netconn_thread_cleanup(void);
#else /* LWIP_NETCONN_SEM_PER_THREAD */
#define netconn_thread_init()
#define netconn_thread_cleanup()
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_NETCONN || LWIP_SOCKET */
#endif /* LWIP_HDR_API_H */
@@ -0,0 +1,79 @@
/**
* @file
* Application layered TCP connection API that executes a proxy-connect.
*
* This file provides a starting layer that executes a proxy-connect e.g. to
* set up TLS connections through a http proxy.
*/
/*
* Copyright (c) 2018 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_APPS_ALTCP_PROXYCONNECT_H
#define LWIP_HDR_APPS_ALTCP_PROXYCONNECT_H
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
#include "lwip/ip_addr.h"
#ifdef __cplusplus
extern "C" {
#endif
struct altcp_proxyconnect_config {
ip_addr_t proxy_addr;
u16_t proxy_port;
};
struct altcp_pcb *altcp_proxyconnect_new(struct altcp_proxyconnect_config *config, struct altcp_pcb *inner_pcb);
struct altcp_pcb *altcp_proxyconnect_new_tcp(struct altcp_proxyconnect_config *config, u8_t ip_type);
struct altcp_pcb *altcp_proxyconnect_alloc(void *arg, u8_t ip_type);
#if LWIP_ALTCP_TLS
struct altcp_proxyconnect_tls_config {
struct altcp_proxyconnect_config proxy;
struct altcp_tls_config *tls_config;
};
struct altcp_pcb *altcp_proxyconnect_tls_alloc(void *arg, u8_t ip_type);
#endif /* LWIP_ALTCP_TLS */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_ALTCP */
#endif /* LWIP_HDR_APPS_ALTCP_PROXYCONNECT_H */
@@ -0,0 +1,67 @@
/**
* @file
* Application layered TCP/TLS connection API (to be used from TCPIP thread)
*
* This file contains options for an mbedtls port of the TLS layer.
*/
/*
* Copyright (c) 2017 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_ALTCP_TLS_OPTS_H
#define LWIP_HDR_ALTCP_TLS_OPTS_H
#include "lwip/opt.h"
#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
/** LWIP_ALTCP_TLS_MBEDTLS==1: use mbedTLS for TLS support for altcp API
* mbedtls include directory must be reachable via include search path
*/
#ifndef LWIP_ALTCP_TLS_MBEDTLS
#define LWIP_ALTCP_TLS_MBEDTLS 0
#endif
/** Configure debug level of this file */
#ifndef ALTCP_MBEDTLS_DEBUG
#define ALTCP_MBEDTLS_DEBUG LWIP_DBG_OFF
#endif
/** Set a session timeout in seconds for the basic session cache
* ATTENTION: Using a session cache can lower security by reusing keys!
*/
#ifndef ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS 0
#endif
#endif /* LWIP_ALTCP */
#endif /* LWIP_HDR_ALTCP_TLS_OPTS_H */
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_APPS_FS_H
#define LWIP_HDR_APPS_FS_H
#include "httpd_opts.h"
#include "lwip/err.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FS_READ_EOF -1
#define FS_READ_DELAYED -2
#if HTTPD_PRECALCULATED_CHECKSUM
struct fsdata_chksum {
u32_t offset;
u16_t chksum;
u16_t len;
};
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
#define FS_FILE_FLAGS_HEADER_INCLUDED 0x01
#define FS_FILE_FLAGS_HEADER_PERSISTENT 0x02
#define FS_FILE_FLAGS_HEADER_HTTPVER_1_1 0x04
#define FS_FILE_FLAGS_SSI 0x08
/** Define FS_FILE_EXTENSION_T_DEFINED if you have typedef'ed to your private
* pointer type (defaults to 'void' so the default usage is 'void*')
*/
#ifndef FS_FILE_EXTENSION_T_DEFINED
typedef void fs_file_extension;
#endif
struct fs_file {
const char *data;
int len;
int index;
/* pextension is free for implementations to hold private (extensional)
arbitrary data, e.g. holding some file state or file system handle */
fs_file_extension *pextension;
#if HTTPD_PRECALCULATED_CHECKSUM
const struct fsdata_chksum *chksum;
u16_t chksum_count;
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
u8_t flags;
#if LWIP_HTTPD_CUSTOM_FILES
u8_t is_custom_file;
#endif /* LWIP_HTTPD_CUSTOM_FILES */
#if LWIP_HTTPD_FILE_STATE
void *state;
#endif /* LWIP_HTTPD_FILE_STATE */
};
#if LWIP_HTTPD_FS_ASYNC_READ
typedef void (*fs_wait_cb)(void *arg);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
err_t fs_open(struct fs_file *file, const char *name);
void fs_close(struct fs_file *file);
#if LWIP_HTTPD_DYNAMIC_FILE_READ
#if LWIP_HTTPD_FS_ASYNC_READ
int fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg);
#else /* LWIP_HTTPD_FS_ASYNC_READ */
int fs_read(struct fs_file *file, char *buffer, int count);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
#if LWIP_HTTPD_FS_ASYNC_READ
int fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
int fs_bytes_left(struct fs_file *file);
#if LWIP_HTTPD_FILE_STATE
/** This user-defined function is called when a file is opened. */
void *fs_state_init(struct fs_file *file, const char *name);
/** This user-defined function is called when a file is closed. */
void fs_state_free(struct fs_file *file, void *state);
#endif /* #if LWIP_HTTPD_FILE_STATE */
struct fsdata_file {
const struct fsdata_file *next;
const unsigned char *name;
const unsigned char *data;
int len;
u8_t flags;
#if HTTPD_PRECALCULATED_CHECKSUM
u16_t chksum_count;
const struct fsdata_chksum *chksum;
#endif /* HTTPD_PRECALCULATED_CHECKSUM */
};
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_FS_H */
@@ -0,0 +1,160 @@
/**
* @file
* HTTP client
*/
/*
* Copyright (c) 2018 Simon Goldschmidt <goldsimon@gmx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt <goldsimon@gmx.de>
*
*/
#ifndef LWIP_HDR_APPS_HTTP_CLIENT_H
#define LWIP_HDR_APPS_HTTP_CLIENT_H
#include "lwip/opt.h"
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#include "lwip/altcp.h"
#include "lwip/prot/iana.h"
#include "lwip/pbuf.h"
#if LWIP_TCP && LWIP_CALLBACK_API
#ifdef __cplusplus
extern "C" {
#endif
/**
* @ingroup httpc
* HTTPC_HAVE_FILE_IO: define this to 1 to have functions dowloading directly
* to disk via fopen/fwrite.
* These functions are example implementations of the interface only.
*/
#ifndef LWIP_HTTPC_HAVE_FILE_IO
#define LWIP_HTTPC_HAVE_FILE_IO 0
#endif
/**
* @ingroup httpc
* The default TCP port used for HTTP
*/
#define HTTP_DEFAULT_PORT LWIP_IANA_PORT_HTTP
/**
* @ingroup httpc
* HTTP client result codes
*/
typedef enum ehttpc_result {
/** File successfully received */
HTTPC_RESULT_OK = 0,
/** Unknown error */
HTTPC_RESULT_ERR_UNKNOWN = 1,
/** Connection to server failed */
HTTPC_RESULT_ERR_CONNECT = 2,
/** Failed to resolve server hostname */
HTTPC_RESULT_ERR_HOSTNAME = 3,
/** Connection unexpectedly closed by remote server */
HTTPC_RESULT_ERR_CLOSED = 4,
/** Connection timed out (server didn't respond in time) */
HTTPC_RESULT_ERR_TIMEOUT = 5,
/** Server responded with an error code */
HTTPC_RESULT_ERR_SVR_RESP = 6,
/** Local memory error */
HTTPC_RESULT_ERR_MEM = 7,
/** Local abort */
HTTPC_RESULT_LOCAL_ABORT = 8,
/** Content length mismatch */
HTTPC_RESULT_ERR_CONTENT_LEN = 9
} httpc_result_t;
typedef struct _httpc_state httpc_state_t;
/**
* @ingroup httpc
* Prototype of a http client callback function
*
* @param arg argument specified when initiating the request
* @param httpc_result result of the http transfer (see enum httpc_result_t)
* @param rx_content_len number of bytes received (without headers)
* @param srv_res this contains the http status code received (if any)
* @param err an error returned by internal lwip functions, can help to specify
* the source of the error but must not necessarily be != ERR_OK
*/
typedef void (*httpc_result_fn)(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, u32_t srv_res, err_t err);
/**
* @ingroup httpc
* Prototype of http client callback: called when the headers are received
*
* @param connection http client connection
* @param arg argument specified when initiating the request
* @param hdr header pbuf(s) (may contain data also)
* @param hdr_len length of the heders in 'hdr'
* @param content_len content length as received in the headers (-1 if not received)
* @return if != ERR_OK is returned, the connection is aborted
*/
typedef err_t (*httpc_headers_done_fn)(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u32_t content_len);
typedef struct _httpc_connection {
ip_addr_t proxy_addr;
u16_t proxy_port;
u8_t use_proxy;
/* @todo: add username:pass? */
#if LWIP_ALTCP
altcp_allocator_t *altcp_allocator;
#endif
/* this callback is called when the transfer is finished (or aborted) */
httpc_result_fn result_fn;
/* this callback is called after receiving the http headers
It can abort the connection by returning != ERR_OK */
httpc_headers_done_fn headers_done_fn;
} httpc_connection_t;
err_t httpc_get_file(const ip_addr_t* server_addr, u16_t port, const char* uri, const httpc_connection_t *settings,
altcp_recv_fn recv_fn, void* callback_arg, httpc_state_t **connection);
err_t httpc_get_file_dns(const char* server_name, u16_t port, const char* uri, const httpc_connection_t *settings,
altcp_recv_fn recv_fn, void* callback_arg, httpc_state_t **connection);
#if LWIP_HTTPC_HAVE_FILE_IO
err_t httpc_get_file_to_disk(const ip_addr_t* server_addr, u16_t port, const char* uri, const httpc_connection_t *settings,
void* callback_arg, const char* local_file_name, httpc_state_t **connection);
err_t httpc_get_file_dns_to_disk(const char* server_name, u16_t port, const char* uri, const httpc_connection_t *settings,
void* callback_arg, const char* local_file_name, httpc_state_t **connection);
#endif /* LWIP_HTTPC_HAVE_FILE_IO */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_TCP && LWIP_CALLBACK_API */
#endif /* LWIP_HDR_APPS_HTTP_CLIENT_H */
@@ -0,0 +1,255 @@
/**
* @file
* HTTP server
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
* This version of the file has been modified by Texas Instruments to offer
* simple server-side-include (SSI) and Common Gateway Interface (CGI)
* capability.
*/
#ifndef LWIP_HDR_APPS_HTTPD_H
#define LWIP_HDR_APPS_HTTPD_H
#include "httpd_opts.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_HTTPD_CGI
/**
* @ingroup httpd
* Function pointer for a CGI script handler.
*
* This function is called each time the HTTPD server is asked for a file
* whose name was previously registered as a CGI function using a call to
* http_set_cgi_handlers. The iIndex parameter provides the index of the
* CGI within the cgis array passed to http_set_cgi_handlers. Parameters
* pcParam and pcValue provide access to the parameters provided along with
* the URI. iNumParams provides a count of the entries in the pcParam and
* pcValue arrays. Each entry in the pcParam array contains the name of a
* parameter with the corresponding entry in the pcValue array containing the
* value for that parameter. Note that pcParam may contain multiple elements
* with the same name if, for example, a multi-selection list control is used
* in the form generating the data.
*
* The function should return a pointer to a character string which is the
* path and filename of the response that is to be sent to the connected
* browser, for example "/thanks.htm" or "/response/error.ssi".
*
* The maximum number of parameters that will be passed to this function via
* iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in
* the incoming HTTP request above this number will be discarded.
*
* Requests intended for use by this CGI mechanism must be sent using the GET
* method (which encodes all parameters within the URI rather than in a block
* later in the request). Attempts to use the POST method will result in the
* request being ignored.
*
*/
typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[],
char *pcValue[]);
/**
* @ingroup httpd
* Structure defining the base filename (URL) of a CGI and the associated
* function which is to be called when that URL is requested.
*/
typedef struct
{
const char *pcCGIName;
tCGIHandler pfnCGIHandler;
} tCGI;
void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers);
#endif /* LWIP_HTTPD_CGI */
#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI
#if LWIP_HTTPD_CGI_SSI
/* we have to prototype this struct here to make it available for the handler */
struct fs_file;
/** Define this generic CGI handler in your application.
* It is called once for every URI with parameters.
* The parameters can be stored to the object passed as connection_state, which
* is allocated to file->state via fs_state_init() from fs_open() or fs_open_custom().
* Content creation via SSI or complete dynamic files can retrieve the CGI params from there.
*/
extern void httpd_cgi_handler(struct fs_file *file, const char* uri, int iNumParams,
char **pcParam, char **pcValue
#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE
, void *connection_state
#endif /* LWIP_HTTPD_FILE_STATE */
);
#endif /* LWIP_HTTPD_CGI_SSI */
#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */
#if LWIP_HTTPD_SSI
/**
* @ingroup httpd
* Function pointer for the SSI tag handler callback.
*
* This function will be called each time the HTTPD server detects a tag of the
* form <!--#name--> in files with extensions mentioned in the g_pcSSIExtensions
* array (currently .shtml, .shtm, .ssi, .xml, .json) where "name" appears as
* one of the tags supplied to http_set_ssi_handler in the tags array. The
* returned insert string, which will be appended after the the string
* "<!--#name-->" in file sent back to the client, should be written to pointer
* pcInsert. iInsertLen contains the size of the buffer pointed to by
* pcInsert. The iIndex parameter provides the zero-based index of the tag as
* found in the tags array and identifies the tag that is to be processed.
*
* The handler returns the number of characters written to pcInsert excluding
* any terminating NULL or HTTPD_SSI_TAG_UNKNOWN when tag is not recognized.
*
* Note that the behavior of this SSI mechanism is somewhat different from the
* "normal" SSI processing as found in, for example, the Apache web server. In
* this case, the inserted text is appended following the SSI tag rather than
* replacing the tag entirely. This allows for an implementation that does not
* require significant additional buffering of output data yet which will still
* offer usable SSI functionality. One downside to this approach is when
* attempting to use SSI within JavaScript. The SSI tag is structured to
* resemble an HTML comment but this syntax does not constitute a comment
* within JavaScript and, hence, leaving the tag in place will result in
* problems in these cases. In order to avoid these problems, define
* LWIP_HTTPD_SSI_INCLUDE_TAG as zero in your lwip options file, or use JavaScript
* style block comments in the form / * # name * / (without the spaces).
*/
typedef u16_t (*tSSIHandler)(
#if LWIP_HTTPD_SSI_RAW
const char* ssi_tag_name,
#else /* LWIP_HTTPD_SSI_RAW */
int iIndex,
#endif /* LWIP_HTTPD_SSI_RAW */
char *pcInsert, int iInsertLen
#if LWIP_HTTPD_SSI_MULTIPART
, u16_t current_tag_part, u16_t *next_tag_part
#endif /* LWIP_HTTPD_SSI_MULTIPART */
#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE
, void *connection_state
#endif /* LWIP_HTTPD_FILE_STATE */
);
/** Set the SSI handler function
* (if LWIP_HTTPD_SSI_RAW==1, only the first argument is used)
*/
void http_set_ssi_handler(tSSIHandler pfnSSIHandler,
const char **ppcTags, int iNumTags);
/** For LWIP_HTTPD_SSI_RAW==1, return this to indicate the tag is unknown.
* In this case, the webserver writes a warning into the page.
* You can also just return 0 to write nothing for unknown tags.
*/
#define HTTPD_SSI_TAG_UNKNOWN 0xFFFF
#endif /* LWIP_HTTPD_SSI */
#if LWIP_HTTPD_SUPPORT_POST
/* These functions must be implemented by the application */
/**
* @ingroup httpd
* Called when a POST request has been received. The application can decide
* whether to accept it or not.
*
* @param connection Unique connection identifier, valid until httpd_post_end
* is called.
* @param uri The HTTP header URI receiving the POST request.
* @param http_request The raw HTTP request (the first packet, normally).
* @param http_request_len Size of 'http_request'.
* @param content_len Content-Length from HTTP header.
* @param response_uri Filename of response file, to be filled when denying the
* request
* @param response_uri_len Size of the 'response_uri' buffer.
* @param post_auto_wnd Set this to 0 to let the callback code handle window
* updates by calling 'httpd_post_data_recved' (to throttle rx speed)
* default is 1 (httpd handles window updates automatically)
* @return ERR_OK: Accept the POST request, data may be passed in
* another err_t: Deny the POST request, send back 'bad request'.
*/
err_t httpd_post_begin(void *connection, const char *uri, const char *http_request,
u16_t http_request_len, int content_len, char *response_uri,
u16_t response_uri_len, u8_t *post_auto_wnd);
/**
* @ingroup httpd
* Called for each pbuf of data that has been received for a POST.
* ATTENTION: The application is responsible for freeing the pbufs passed in!
*
* @param connection Unique connection identifier.
* @param p Received data.
* @return ERR_OK: Data accepted.
* another err_t: Data denied, http_post_get_response_uri will be called.
*/
err_t httpd_post_receive_data(void *connection, struct pbuf *p);
/**
* @ingroup httpd
* Called when all data is received or when the connection is closed.
* The application must return the filename/URI of a file to send in response
* to this POST request. If the response_uri buffer is untouched, a 404
* response is returned.
*
* @param connection Unique connection identifier.
* @param response_uri Filename of response file, to be filled when denying the request
* @param response_uri_len Size of the 'response_uri' buffer.
*/
void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len);
#if LWIP_HTTPD_POST_MANUAL_WND
void httpd_post_data_recved(void *connection, u16_t recved_len);
#endif /* LWIP_HTTPD_POST_MANUAL_WND */
#endif /* LWIP_HTTPD_SUPPORT_POST */
void httpd_init(void);
#if HTTPD_ENABLE_HTTPS
struct altcp_tls_config;
void httpd_inits(struct altcp_tls_config *conf);
#endif
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_HTTPD_H */
@@ -0,0 +1,396 @@
/**
* @file
* HTTP server options list
*/
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
* This version of the file has been modified by Texas Instruments to offer
* simple server-side-include (SSI) and Common Gateway Interface (CGI)
* capability.
*/
#ifndef LWIP_HDR_APPS_HTTPD_OPTS_H
#define LWIP_HDR_APPS_HTTPD_OPTS_H
#include "lwip/opt.h"
#include "lwip/prot/iana.h"
/**
* @defgroup httpd_opts Options
* @ingroup httpd
* @{
*/
/** Set this to 1 to support CGI (old style).
*
* This old style CGI support works by registering an array of URLs and
* associated CGI handler functions (@ref http_set_cgi_handlers).
* This list is scanned just before fs_open is called from request handling.
* The handler can return a new URL that is used internally by the httpd to
* load the returned page (passed to fs_open).
*
* Use this CGI type e.g. to execute specific actions and return a page that
* does not depend on the CGI parameters.
*/
#if !defined LWIP_HTTPD_CGI || defined __DOXYGEN__
#define LWIP_HTTPD_CGI 0
#endif
/** Set this to 1 to support CGI (new style).
*
* This new style CGI support works by calling a global function
* (@ref tCGIHandler) for all URLs that are found. fs_open is called first
* and the URL can not be written by the CGI handler. Instead, this handler gets
* passed the http file state, an object where it can store information derived
* from the CGI URL or parameters. This file state is later passed to SSI, so
* the SSI code can return data depending on CGI input.
*
* Use this CGI handler if you want CGI information passed on to SSI.
*/
#if !defined LWIP_HTTPD_CGI_SSI || defined __DOXYGEN__
#define LWIP_HTTPD_CGI_SSI 0
#endif
/** Set this to 1 to support SSI (Server-Side-Includes)
*
* In contrast to other http servers, this only calls a preregistered callback
* function (@see http_set_ssi_handler) for each tag (in the format of
* <!--#tag-->) encountered in SSI-enabled pages.
* SSI-enabled pages must have one of the predefined SSI-enabled file extensions.
* All files with one of these extensions are parsed when sent.
*
* A downside of the current SSI implementation is that persistent connections
* don't work, as the file length is not known in advance (and httpd currently
* relies on the Content-Length header for persistent connections).
*
* To save memory, the maximum tag length is limited (@see LWIP_HTTPD_MAX_TAG_NAME_LEN).
* To save memory, the maximum insertion string length is limited (@see
* LWIP_HTTPD_MAX_TAG_INSERT_LEN). If this is not enought, @ref LWIP_HTTPD_SSI_MULTIPART
* can be used.
*/
#if !defined LWIP_HTTPD_SSI || defined __DOXYGEN__
#define LWIP_HTTPD_SSI 0
#endif
/** Set this to 1 to implement an SSI tag handler callback that gets a const char*
* to the tag (instead of an index into a pre-registered array of known tags)
* If this is 0, the SSI handler callback function is only called pre-registered tags.
*/
#if !defined LWIP_HTTPD_SSI_RAW || defined __DOXYGEN__
#define LWIP_HTTPD_SSI_RAW 0
#endif
/** Set this to 0 to prevent parsing the file extension at runtime to decide
* if a file should be scanned for SSI tags or not.
* Default is 1 (file extensions are checked using the g_pcSSIExtensions array)
* Set to 2 to override this runtime test function.
*
* This is enabled by default, but if you only use a newer version of makefsdata
* supporting the "-ssi" option, this info is already present in
*/
#if !defined LWIP_HTTPD_SSI_BY_FILE_EXTENSION || defined __DOXYGEN__
#define LWIP_HTTPD_SSI_BY_FILE_EXTENSION 1
#endif
/** Set this to 1 to support HTTP POST */
#if !defined LWIP_HTTPD_SUPPORT_POST || defined __DOXYGEN__
#define LWIP_HTTPD_SUPPORT_POST 0
#endif
/* The maximum number of parameters that the CGI handler can be sent. */
#if !defined LWIP_HTTPD_MAX_CGI_PARAMETERS || defined __DOXYGEN__
#define LWIP_HTTPD_MAX_CGI_PARAMETERS 16
#endif
/** LWIP_HTTPD_SSI_MULTIPART==1: SSI handler function is called with 2 more
* arguments indicating a counter for insert string that are too long to be
* inserted at once: the SSI handler function must then set 'next_tag_part'
* which will be passed back to it in the next call. */
#if !defined LWIP_HTTPD_SSI_MULTIPART || defined __DOXYGEN__
#define LWIP_HTTPD_SSI_MULTIPART 0
#endif
/* The maximum length of the string comprising the SSI tag name
* ATTENTION: tags longer than this are ignored, not truncated!
*/
#if !defined LWIP_HTTPD_MAX_TAG_NAME_LEN || defined __DOXYGEN__
#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8
#endif
/* The maximum length of string that can be returned to replace any given tag
* If this buffer is not long enough, use LWIP_HTTPD_SSI_MULTIPART.
*/
#if !defined LWIP_HTTPD_MAX_TAG_INSERT_LEN || defined __DOXYGEN__
#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192
#endif
#if !defined LWIP_HTTPD_POST_MANUAL_WND || defined __DOXYGEN__
#define LWIP_HTTPD_POST_MANUAL_WND 0
#endif
/** This string is passed in the HTTP header as "Server: " */
#if !defined HTTPD_SERVER_AGENT || defined __DOXYGEN__
#define HTTPD_SERVER_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)"
#endif
/** Set this to 1 if you want to include code that creates HTTP headers
* at runtime. Default is off: HTTP headers are then created statically
* by the makefsdata tool. Static headers mean smaller code size, but
* the (readonly) fsdata will grow a bit as every file includes the HTTP
* header. */
#if !defined LWIP_HTTPD_DYNAMIC_HEADERS || defined __DOXYGEN__
#define LWIP_HTTPD_DYNAMIC_HEADERS 0
#endif
#if !defined HTTPD_DEBUG || defined __DOXYGEN__
#define HTTPD_DEBUG LWIP_DBG_OFF
#endif
/** Set this to 1 to use a memp pool for allocating
* struct http_state instead of the heap.
* If enabled, you'll need to define MEMP_NUM_PARALLEL_HTTPD_CONNS
* (and MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS for SSI) to set the size of
* the pool(s).
*/
#if !defined HTTPD_USE_MEM_POOL || defined __DOXYGEN__
#define HTTPD_USE_MEM_POOL 0
#endif
/** The server port for HTTPD to use */
#if !defined HTTPD_SERVER_PORT || defined __DOXYGEN__
#define HTTPD_SERVER_PORT LWIP_IANA_PORT_HTTP
#endif
/** The https server port for HTTPD to use */
#if !defined HTTPD_SERVER_PORT_HTTPS || defined __DOXYGEN__
#define HTTPD_SERVER_PORT_HTTPS LWIP_IANA_PORT_HTTPS
#endif
/** Enable https support? */
#if !defined HTTPD_ENABLE_HTTPS || defined __DOXYGEN__
#define HTTPD_ENABLE_HTTPS 0
#endif
/** Maximum retries before the connection is aborted/closed.
* - number of times pcb->poll is called -> default is 4*500ms = 2s;
* - reset when pcb->sent is called
*/
#if !defined HTTPD_MAX_RETRIES || defined __DOXYGEN__
#define HTTPD_MAX_RETRIES 4
#endif
/** The poll delay is X*500ms */
#if !defined HTTPD_POLL_INTERVAL || defined __DOXYGEN__
#define HTTPD_POLL_INTERVAL 4
#endif
/** Priority for tcp pcbs created by HTTPD (very low by default).
* Lower priorities get killed first when running out of memory.
*/
#if !defined HTTPD_TCP_PRIO || defined __DOXYGEN__
#define HTTPD_TCP_PRIO TCP_PRIO_MIN
#endif
/** Set this to 1 to enable timing each file sent */
#if !defined LWIP_HTTPD_TIMING || defined __DOXYGEN__
#define LWIP_HTTPD_TIMING 0
#endif
/** Set this to 1 to enable timing each file sent */
#if !defined HTTPD_DEBUG_TIMING || defined __DOXYGEN__
#define HTTPD_DEBUG_TIMING LWIP_DBG_OFF
#endif
/** Set this to one to show error pages when parsing a request fails instead
of simply closing the connection. */
#if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__
#define LWIP_HTTPD_SUPPORT_EXTSTATUS 0
#endif
/** Set this to 0 to drop support for HTTP/0.9 clients (to save some bytes) */
#if !defined LWIP_HTTPD_SUPPORT_V09 || defined __DOXYGEN__
#define LWIP_HTTPD_SUPPORT_V09 1
#endif
/** Set this to 1 to enable HTTP/1.1 persistent connections.
* ATTENTION: If the generated file system includes HTTP headers, these must
* include the "Connection: keep-alive" header (pass argument "-11" to makefsdata).
*/
#if !defined LWIP_HTTPD_SUPPORT_11_KEEPALIVE || defined __DOXYGEN__
#define LWIP_HTTPD_SUPPORT_11_KEEPALIVE 0
#endif
/** Set this to 1 to support HTTP request coming in in multiple packets/pbufs */
#if !defined LWIP_HTTPD_SUPPORT_REQUESTLIST || defined __DOXYGEN__
#define LWIP_HTTPD_SUPPORT_REQUESTLIST 1
#endif
#if LWIP_HTTPD_SUPPORT_REQUESTLIST
/** Number of rx pbufs to enqueue to parse an incoming request (up to the first
newline) */
#if !defined LWIP_HTTPD_REQ_QUEUELEN || defined __DOXYGEN__
#define LWIP_HTTPD_REQ_QUEUELEN 5
#endif
/** Number of (TCP payload-) bytes (in pbufs) to enqueue to parse and incoming
request (up to the first double-newline) */
#if !defined LWIP_HTTPD_REQ_BUFSIZE || defined __DOXYGEN__
#define LWIP_HTTPD_REQ_BUFSIZE LWIP_HTTPD_MAX_REQ_LENGTH
#endif
/** Defines the maximum length of a HTTP request line (up to the first CRLF,
copied from pbuf into this a global buffer when pbuf- or packet-queues
are received - otherwise the input pbuf is used directly) */
#if !defined LWIP_HTTPD_MAX_REQ_LENGTH || defined __DOXYGEN__
#define LWIP_HTTPD_MAX_REQ_LENGTH LWIP_MIN(1023, (LWIP_HTTPD_REQ_QUEUELEN * PBUF_POOL_BUFSIZE))
#endif
#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
/** This is the size of a static buffer used when URIs end with '/'.
* In this buffer, the directory requested is concatenated with all the
* configured default file names.
* Set to 0 to disable checking default filenames on non-root directories.
*/
#if !defined LWIP_HTTPD_MAX_REQUEST_URI_LEN || defined __DOXYGEN__
#define LWIP_HTTPD_MAX_REQUEST_URI_LEN 63
#endif
/** Maximum length of the filename to send as response to a POST request,
* filled in by the application when a POST is finished.
*/
#if !defined LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN || defined __DOXYGEN__
#define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN 63
#endif
/** Set this to 0 to not send the SSI tag (default is on, so the tag will
* be sent in the HTML page */
#if !defined LWIP_HTTPD_SSI_INCLUDE_TAG || defined __DOXYGEN__
#define LWIP_HTTPD_SSI_INCLUDE_TAG 1
#endif
/** Set this to 1 to call tcp_abort when tcp_close fails with memory error.
* This can be used to prevent consuming all memory in situations where the
* HTTP server has low priority compared to other communication. */
#if !defined LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR || defined __DOXYGEN__
#define LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR 0
#endif
/** Set this to 1 to kill the oldest connection when running out of
* memory for 'struct http_state' or 'struct http_ssi_state'.
* ATTENTION: This puts all connections on a linked list, so may be kind of slow.
*/
#if !defined LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED || defined __DOXYGEN__
#define LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 0
#endif
/** Set this to 1 to send URIs without extension without headers
* (who uses this at all??) */
#if !defined LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI || defined __DOXYGEN__
#define LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI 0
#endif
/** Default: Tags are sent from struct http_state and are therefore volatile */
#if !defined HTTP_IS_TAG_VOLATILE || defined __DOXYGEN__
#define HTTP_IS_TAG_VOLATILE(ptr) TCP_WRITE_FLAG_COPY
#endif
/* By default, the httpd is limited to send 2*pcb->mss to keep resource usage low
when http is not an important protocol in the device. */
#if !defined HTTPD_LIMIT_SENDING_TO_2MSS || defined __DOXYGEN__
#define HTTPD_LIMIT_SENDING_TO_2MSS 1
#endif
/* Define this to a function that returns the maximum amount of data to enqueue.
The function have this signature: u16_t fn(struct altcp_pcb* pcb);
The best place to define this is the hooks file (@see LWIP_HOOK_FILENAME) */
#if !defined HTTPD_MAX_WRITE_LEN || defined __DOXYGEN__
#if HTTPD_LIMIT_SENDING_TO_2MSS
#define HTTPD_MAX_WRITE_LEN(pcb) ((u16_t)(2 * altcp_mss(pcb)))
#endif
#endif
/*------------------- FS OPTIONS -------------------*/
/** Set this to 1 and provide the functions:
* - "int fs_open_custom(struct fs_file *file, const char *name)"
* Called first for every opened file to allow opening files
* that are not included in fsdata(_custom).c
* - "void fs_close_custom(struct fs_file *file)"
* Called to free resources allocated by fs_open_custom().
*/
#if !defined LWIP_HTTPD_CUSTOM_FILES || defined __DOXYGEN__
#define LWIP_HTTPD_CUSTOM_FILES 0
#endif
/** Set this to 1 to support fs_read() to dynamically read file data.
* Without this (default=off), only one-block files are supported,
* and the contents must be ready after fs_open().
*/
#if !defined LWIP_HTTPD_DYNAMIC_FILE_READ || defined __DOXYGEN__
#define LWIP_HTTPD_DYNAMIC_FILE_READ 0
#endif
/** Set this to 1 to include an application state argument per file
* that is opened. This allows to keep a state per connection/file.
*/
#if !defined LWIP_HTTPD_FILE_STATE || defined __DOXYGEN__
#define LWIP_HTTPD_FILE_STATE 0
#endif
/** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for
* predefined (MSS-sized) chunks of the files to prevent having to calculate
* the checksums at runtime. */
#if !defined HTTPD_PRECALCULATED_CHECKSUM || defined __DOXYGEN__
#define HTTPD_PRECALCULATED_CHECKSUM 0
#endif
/** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations
* (fs_read_async returns FS_READ_DELAYED and calls a callback when finished).
*/
#if !defined LWIP_HTTPD_FS_ASYNC_READ || defined __DOXYGEN__
#define LWIP_HTTPD_FS_ASYNC_READ 0
#endif
/** Filename (including path) to use as FS data file */
#if !defined HTTPD_FSDATA_FILE || defined __DOXYGEN__
/* HTTPD_USE_CUSTOM_FSDATA: Compatibility with deprecated lwIP option */
#if defined(HTTPD_USE_CUSTOM_FSDATA) && (HTTPD_USE_CUSTOM_FSDATA != 0)
#define HTTPD_FSDATA_FILE "fsdata.c"
#else
#define HTTPD_FSDATA_FILE "fsdata.c"
#endif
#endif
/**
* @}
*/
#endif /* LWIP_HDR_APPS_HTTPD_OPTS_H */
@@ -0,0 +1,100 @@
/**
* @file
* lwIP iPerf server implementation
*/
/*
* Copyright (c) 2014 Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Simon Goldschmidt
*
*/
#ifndef LWIP_HDR_APPS_LWIPERF_H
#define LWIP_HDR_APPS_LWIPERF_H
#include "lwip/opt.h"
#include "lwip/ip_addr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LWIPERF_TCP_PORT_DEFAULT 5001
/** lwIPerf test results */
enum lwiperf_report_type
{
/** The server side test is done */
LWIPERF_TCP_DONE_SERVER,
/** The client side test is done */
LWIPERF_TCP_DONE_CLIENT,
/** Local error lead to test abort */
LWIPERF_TCP_ABORTED_LOCAL,
/** Data check error lead to test abort */
LWIPERF_TCP_ABORTED_LOCAL_DATAERROR,
/** Transmit error lead to test abort */
LWIPERF_TCP_ABORTED_LOCAL_TXERROR,
/** Remote side aborted the test */
LWIPERF_TCP_ABORTED_REMOTE
};
/** Control */
enum lwiperf_client_type
{
/** Unidirectional tx only test */
LWIPERF_CLIENT,
/** Do a bidirectional test simultaneously */
LWIPERF_DUAL,
/** Do a bidirectional test individually */
LWIPERF_TRADEOFF
};
/** Prototype of a report function that is called when a session is finished.
This report function can show the test results.
@param report_type contains the test result */
typedef void (*lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type,
const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port,
u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec);
void* lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port,
lwiperf_report_fn report_fn, void* report_arg);
void* lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg);
void* lwiperf_start_tcp_client(const ip_addr_t* remote_addr, u16_t remote_port,
enum lwiperf_client_type type,
lwiperf_report_fn report_fn, void* report_arg);
void* lwiperf_start_tcp_client_default(const ip_addr_t* remote_addr,
lwiperf_report_fn report_fn, void* report_arg);
void lwiperf_abort(void* lwiperf_session);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_LWIPERF_H */
@@ -0,0 +1,105 @@
/**
* @file
* MDNS responder
*/
/*
* Copyright (c) 2015 Verisure Innovation AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik@kryo.se>
*
*/
#ifndef LWIP_HDR_APPS_MDNS_H
#define LWIP_HDR_APPS_MDNS_H
#include "lwip/apps/mdns_opts.h"
#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_MDNS_RESPONDER
enum mdns_sd_proto {
DNSSD_PROTO_UDP = 0,
DNSSD_PROTO_TCP = 1
};
#define MDNS_PROBING_CONFLICT 0
#define MDNS_PROBING_SUCCESSFUL 1
#define MDNS_LABEL_MAXLEN 63
struct mdns_host;
struct mdns_service;
/** Callback function to add text to a reply, called when generating the reply */
typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata);
/** Callback function to let application know the result of probing network for name
* uniqueness, called with result MDNS_PROBING_SUCCESSFUL if no other node claimed
* use for the name for the netif or a service and is safe to use, or MDNS_PROBING_CONFLICT
* if another node is already using it and mdns is disabled on this interface */
typedef void (*mdns_name_result_cb_t)(struct netif* netif, u8_t result);
void mdns_resp_init(void);
void mdns_resp_register_name_result_cb(mdns_name_result_cb_t cb);
err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl);
err_t mdns_resp_remove_netif(struct netif *netif);
err_t mdns_resp_rename_netif(struct netif *netif, const char *hostname);
s8_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata);
err_t mdns_resp_del_service(struct netif *netif, s8_t slot);
err_t mdns_resp_rename_service(struct netif *netif, s8_t slot, const char *name);
err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len);
void mdns_resp_restart(struct netif *netif);
void mdns_resp_announce(struct netif *netif);
/**
* @ingroup mdns
* Announce IP settings have changed on netif.
* Call this in your callback registered by netif_set_status_callback().
* No need to call this function when LWIP_NETIF_EXT_STATUS_CALLBACK==1,
* this handled automatically for you.
* @param netif The network interface where settings have changed.
*/
#define mdns_resp_netif_settings_changed(netif) mdns_resp_announce(netif)
#endif /* LWIP_MDNS_RESPONDER */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_MDNS_H */
@@ -0,0 +1,81 @@
/**
* @file
* MDNS responder
*/
/*
* Copyright (c) 2015 Verisure Innovation AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik@kryo.se>
*
*/
#ifndef LWIP_HDR_APPS_MDNS_OPTS_H
#define LWIP_HDR_APPS_MDNS_OPTS_H
#include "lwip/opt.h"
/**
* @defgroup mdns_opts Options
* @ingroup mdns
* @{
*/
/**
* LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS
* transport. IGMP is needed for IPv4 multicast.
*/
#ifndef LWIP_MDNS_RESPONDER
#define LWIP_MDNS_RESPONDER 0
#endif /* LWIP_MDNS_RESPONDER */
/** The maximum number of services per netif */
#ifndef MDNS_MAX_SERVICES
#define MDNS_MAX_SERVICES 1
#endif
/** MDNS_RESP_USENETIF_EXTCALLBACK==1: register an ext_callback on the netif
* to automatically restart probing/announcing on status or address change.
*/
#ifndef MDNS_RESP_USENETIF_EXTCALLBACK
#define MDNS_RESP_USENETIF_EXTCALLBACK LWIP_NETIF_EXT_STATUS_CALLBACK
#endif
/**
* MDNS_DEBUG: Enable debugging for multicast DNS.
*/
#ifndef MDNS_DEBUG
#define MDNS_DEBUG LWIP_DBG_OFF
#endif
/**
* @}
*/
#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */
@@ -0,0 +1,74 @@
/**
* @file
* MDNS responder private definitions
*/
/*
* Copyright (c) 2015 Verisure Innovation AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Ekman <erik@kryo.se>
*
*/
#ifndef LWIP_HDR_MDNS_PRIV_H
#define LWIP_HDR_MDNS_PRIV_H
#include "lwip/apps/mdns_opts.h"
#include "lwip/pbuf.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_MDNS_RESPONDER
/* Domain struct and methods - visible for unit tests */
#define MDNS_DOMAIN_MAXLEN 256
#define MDNS_READNAME_ERROR 0xFFFF
struct mdns_domain {
/* Encoded domain name */
u8_t name[MDNS_DOMAIN_MAXLEN];
/* Total length of domain name, including zero */
u16_t length;
/* Set if compression of this domain is not allowed */
u8_t skip_compression;
};
err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len);
u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain);
int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b);
u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain);
#endif /* LWIP_MDNS_RESPONDER */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_MDNS_PRIV_H */
@@ -0,0 +1,205 @@
/**
* @file
* MQTT client
*/
/*
* Copyright (c) 2016 Erik Andersson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Andersson
*
*/
#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H
#define LWIP_HDR_APPS_MQTT_CLIENT_H
#include "lwip/apps/mqtt_opts.h"
#include "lwip/err.h"
#include "lwip/ip_addr.h"
#include "lwip/prot/iana.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct mqtt_client_s mqtt_client_t;
#if LWIP_ALTCP && LWIP_ALTCP_TLS
struct altcp_tls_config;
#endif
/** @ingroup mqtt
* Default MQTT port (non-TLS) */
#define MQTT_PORT LWIP_IANA_PORT_MQTT
/** @ingroup mqtt
* Default MQTT TLS port */
#define MQTT_TLS_PORT LWIP_IANA_PORT_SECURE_MQTT
/*---------------------------------------------------------------------------------------------- */
/* Connection with server */
/**
* @ingroup mqtt
* Client information and connection parameters */
struct mqtt_connect_client_info_t {
/** Client identifier, must be set by caller */
const char *client_id;
/** User name, set to NULL if not used */
const char* client_user;
/** Password, set to NULL if not used */
const char* client_pass;
/** keep alive time in seconds, 0 to disable keep alive functionality*/
u16_t keep_alive;
/** will topic, set to NULL if will is not to be used,
will_msg, will_qos and will retain are then ignored */
const char* will_topic;
/** will_msg, see will_topic */
const char* will_msg;
/** will_qos, see will_topic */
u8_t will_qos;
/** will_retain, see will_topic */
u8_t will_retain;
#if LWIP_ALTCP && LWIP_ALTCP_TLS
/** TLS configuration for secure connections */
struct altcp_tls_config *tls_config;
#endif
};
/**
* @ingroup mqtt
* Connection status codes */
typedef enum
{
/** Accepted */
MQTT_CONNECT_ACCEPTED = 0,
/** Refused protocol version */
MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1,
/** Refused identifier */
MQTT_CONNECT_REFUSED_IDENTIFIER = 2,
/** Refused server */
MQTT_CONNECT_REFUSED_SERVER = 3,
/** Refused user credentials */
MQTT_CONNECT_REFUSED_USERNAME_PASS = 4,
/** Refused not authorized */
MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5,
/** Disconnected */
MQTT_CONNECT_DISCONNECTED = 256,
/** Timeout */
MQTT_CONNECT_TIMEOUT = 257
} mqtt_connection_status_t;
/**
* @ingroup mqtt
* Function prototype for mqtt connection status callback. Called when
* client has connected to the server after initiating a mqtt connection attempt by
* calling mqtt_client_connect() or when connection is closed by server or an error
*
* @param client MQTT client itself
* @param arg Additional argument to pass to the callback function
* @param status Connect result code or disconnection notification @see mqtt_connection_status_t
*
*/
typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status);
/**
* @ingroup mqtt
* Data callback flags */
enum {
/** Flag set when last fragment of data arrives in data callback */
MQTT_DATA_FLAG_LAST = 1
};
/**
* @ingroup mqtt
* Function prototype for MQTT incoming publish data callback function. Called when data
* arrives to a subscribed topic @see mqtt_subscribe
*
* @param arg Additional argument to pass to the callback function
* @param data User data, pointed object, data may not be referenced after callback return,
NULL is passed when all publish data are delivered
* @param len Length of publish data fragment
* @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message
*
*/
typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags);
/**
* @ingroup mqtt
* Function prototype for MQTT incoming publish function. Called when an incoming publish
* arrives to a subscribed topic @see mqtt_subscribe
*
* @param arg Additional argument to pass to the callback function
* @param topic Zero terminated Topic text string, topic may not be referenced after callback return
* @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked
*/
typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len);
/**
* @ingroup mqtt
* Function prototype for mqtt request callback. Called when a subscribe, unsubscribe
* or publish request has completed
* @param arg Pointer to user data supplied when invoking request
* @param err ERR_OK on success
* ERR_TIMEOUT if no response was received within timeout,
* ERR_ABRT if (un)subscribe was denied
*/
typedef void (*mqtt_request_cb_t)(void *arg, err_t err);
err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg,
const struct mqtt_connect_client_info_t *client_info);
void mqtt_disconnect(mqtt_client_t *client);
mqtt_client_t *mqtt_client_new(void);
void mqtt_client_free(mqtt_client_t* client);
u8_t mqtt_client_is_connected(mqtt_client_t *client);
void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t,
mqtt_incoming_data_cb_t data_cb, void *arg);
err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub);
/** @ingroup mqtt
*Subscribe to topic */
#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1)
/** @ingroup mqtt
* Unsubscribe to topic */
#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0)
err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain,
mqtt_request_cb_t cb, void *arg);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */
@@ -0,0 +1,103 @@
/**
* @file
* MQTT client options
*/
/*
* Copyright (c) 2016 Erik Andersson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Andersson
*
*/
#ifndef LWIP_HDR_APPS_MQTT_OPTS_H
#define LWIP_HDR_APPS_MQTT_OPTS_H
#include "lwip/opt.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup mqtt_opts Options
* @ingroup mqtt
* @{
*/
/**
* Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads
*/
#ifndef MQTT_OUTPUT_RINGBUF_SIZE
#define MQTT_OUTPUT_RINGBUF_SIZE 256
#endif
/**
* Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8
* If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8
*/
#ifndef MQTT_VAR_HEADER_BUFFER_LEN
#define MQTT_VAR_HEADER_BUFFER_LEN 128
#endif
/**
* Maximum number of pending subscribe, unsubscribe and publish requests to server .
*/
#ifndef MQTT_REQ_MAX_IN_FLIGHT
#define MQTT_REQ_MAX_IN_FLIGHT 4
#endif
/**
* Seconds between each cyclic timer call.
*/
#ifndef MQTT_CYCLIC_TIMER_INTERVAL
#define MQTT_CYCLIC_TIMER_INTERVAL 5
#endif
/**
* Publish, subscribe and unsubscribe request timeout in seconds.
*/
#ifndef MQTT_REQ_TIMEOUT
#define MQTT_REQ_TIMEOUT 30
#endif
/**
* Seconds for MQTT connect response timeout after sending connect request
*/
#ifndef MQTT_CONNECT_TIMOUT
#define MQTT_CONNECT_TIMOUT 100
#endif
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */
@@ -0,0 +1,104 @@
/**
* @file
* MQTT client (private interface)
*/
/*
* Copyright (c) 2016 Erik Andersson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Erik Andersson
*
*/
#ifndef LWIP_HDR_APPS_MQTT_PRIV_H
#define LWIP_HDR_APPS_MQTT_PRIV_H
#include "lwip/apps/mqtt.h"
#include "lwip/altcp.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Pending request item, binds application callback to pending server requests */
struct mqtt_request_t
{
/** Next item in list, NULL means this is the last in chain,
next pointing at itself means request is unallocated */
struct mqtt_request_t *next;
/** Callback to upper layer */
mqtt_request_cb_t cb;
void *arg;
/** MQTT packet identifier */
u16_t pkt_id;
/** Expire time relative to element before this */
u16_t timeout_diff;
};
/** Ring buffer */
struct mqtt_ringbuf_t {
u16_t put;
u16_t get;
u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE];
};
/** MQTT client */
struct mqtt_client_s
{
/** Timers and timeouts */
u16_t cyclic_tick;
u16_t keep_alive;
u16_t server_watchdog;
/** Packet identifier generator*/
u16_t pkt_id_seq;
/** Packet identifier of pending incoming publish */
u16_t inpub_pkt_id;
/** Connection state */
u8_t conn_state;
struct altcp_pcb *conn;
/** Connection callback */
void *connect_arg;
mqtt_connection_cb_t connect_cb;
/** Pending requests to server */
struct mqtt_request_t *pend_req_queue;
struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT];
void *inpub_arg;
/** Incoming data callback */
mqtt_incoming_data_cb_t data_cb;
mqtt_incoming_publish_cb_t pub_cb;
/** Input */
u32_t msg_idx;
u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN];
/** Output ring-buffer */
struct mqtt_ringbuf_t output;
};
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_MQTT_PRIV_H */
@@ -0,0 +1,51 @@
/**
* @file
* NETBIOS name service responder
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#ifndef LWIP_HDR_APPS_NETBIOS_H
#define LWIP_HDR_APPS_NETBIOS_H
#include "lwip/apps/netbiosns_opts.h"
#ifdef __cplusplus
extern "C" {
#endif
void netbiosns_init(void);
#ifndef NETBIOS_LWIP_NAME
void netbiosns_set_name(const char* hostname);
#endif
void netbiosns_stop(void);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_NETBIOS_H */
@@ -0,0 +1,66 @@
/**
* @file
* NETBIOS name service responder options
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#ifndef LWIP_HDR_APPS_NETBIOS_OPTS_H
#define LWIP_HDR_APPS_NETBIOS_OPTS_H
#include "lwip/opt.h"
/**
* @defgroup netbiosns_opts Options
* @ingroup netbiosns
* @{
*/
/** NetBIOS name of lwip device
* This must be uppercase until NETBIOS_STRCMP() is defined to a string
* comparision function that is case insensitive.
* If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME):
* (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "")
*
* If this is not defined, netbiosns_set_name() can be called at runtime to change the name.
*/
#ifdef __DOXYGEN__
#define NETBIOS_LWIP_NAME "NETBIOSLWIPDEV"
#endif
/** Respond to NetBIOS name queries
* Default is disabled
*/
#if !defined LWIP_NETBIOS_RESPOND_NAME_QUERY || defined __DOXYGEN__
#define LWIP_NETBIOS_RESPOND_NAME_QUERY 0
#endif
/**
* @}
*/
#endif /* LWIP_HDR_APPS_NETBIOS_OPTS_H */
@@ -0,0 +1,128 @@
#ifndef LWIP_HDR_APPS_SMTP_H
#define LWIP_HDR_APPS_SMTP_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lwip/apps/smtp_opts.h"
#include "lwip/err.h"
#include "lwip/prot/iana.h"
/** The default TCP port used for SMTP */
#define SMTP_DEFAULT_PORT LWIP_IANA_PORT_SMTP
/** The default TCP port used for SMTPS */
#define SMTPS_DEFAULT_PORT LWIP_IANA_PORT_SMTPS
/** Email successfully sent */
#define SMTP_RESULT_OK 0
/** Unknown error */
#define SMTP_RESULT_ERR_UNKNOWN 1
/** Connection to server failed */
#define SMTP_RESULT_ERR_CONNECT 2
/** Failed to resolve server hostname */
#define SMTP_RESULT_ERR_HOSTNAME 3
/** Connection unexpectedly closed by remote server */
#define SMTP_RESULT_ERR_CLOSED 4
/** Connection timed out (server didn't respond in time) */
#define SMTP_RESULT_ERR_TIMEOUT 5
/** Server responded with an unknown response code */
#define SMTP_RESULT_ERR_SVR_RESP 6
/** Out of resources locally */
#define SMTP_RESULT_ERR_MEM 7
/** Prototype of an smtp callback function
*
* @param arg argument specified when initiating the email
* @param smtp_result result of the mail transfer (see defines SMTP_RESULT_*)
* @param srv_err if aborted by the server, this contains the error code received
* @param err an error returned by internal lwip functions, can help to specify
* the source of the error but must not necessarily be != ERR_OK
*/
typedef void (*smtp_result_fn)(void *arg, u8_t smtp_result, u16_t srv_err, err_t err);
/** This structure is used as argument for smtp_send_mail_int(),
* which in turn can be used with tcpip_callback() to send mail
* from interrupt context, e.g. like this:
* struct smtp_send_request *req; (to be filled)
* tcpip_try_callback(smtp_send_mail_int, (void*)req);
*
* For member description, see parameter description of smtp_send_mail().
* When using with tcpip_callback, this structure has to stay allocated
* (e.g. using mem_malloc/mem_free) until its 'callback_fn' is called.
*/
struct smtp_send_request {
const char *from;
const char* to;
const char* subject;
const char* body;
smtp_result_fn callback_fn;
void* callback_arg;
/** If this is != 0, data is *not* copied into an extra buffer
* but used from the pointers supplied in this struct.
* This means less memory usage, but data must stay untouched until
* the callback function is called. */
u8_t static_data;
};
#if SMTP_BODYDH
#ifndef SMTP_BODYDH_BUFFER_SIZE
#define SMTP_BODYDH_BUFFER_SIZE 256
#endif /* SMTP_BODYDH_BUFFER_SIZE */
struct smtp_bodydh {
u16_t state;
u16_t length; /* Length of content in buffer */
char buffer[SMTP_BODYDH_BUFFER_SIZE]; /* buffer for generated content */
#ifdef SMTP_BODYDH_USER_SIZE
u8_t user[SMTP_BODYDH_USER_SIZE];
#endif /* SMTP_BODYDH_USER_SIZE */
};
enum bdh_retvals_e {
BDH_DONE = 0,
BDH_WORKING
};
/** Prototype of an smtp body callback function
* It receives a struct smtp_bodydh, and a buffer to write data,
* must return BDH_WORKING to be called again and BDH_DONE when
* it has finished processing. This one tries to fill one TCP buffer with
* data, your function will be repeatedly called until that happens; so if you
* know you'll be taking too long to serve your request, pause once in a while
* by writing length=0 to avoid hogging system resources
*
* @param arg argument specified when initiating the email
* @param smtp_bodydh state handling + buffer structure
*/
typedef int (*smtp_bodycback_fn)(void *arg, struct smtp_bodydh *bodydh);
err_t smtp_send_mail_bodycback(const char *from, const char* to, const char* subject,
smtp_bodycback_fn bodycback_fn, smtp_result_fn callback_fn, void* callback_arg);
#endif /* SMTP_BODYDH */
err_t smtp_set_server_addr(const char* server);
void smtp_set_server_port(u16_t port);
#if LWIP_ALTCP && LWIP_ALTCP_TLS
struct altcp_tls_config;
void smtp_set_tls_config(struct altcp_tls_config *tls_config);
#endif
err_t smtp_set_auth(const char* username, const char* pass);
err_t smtp_send_mail(const char *from, const char* to, const char* subject, const char* body,
smtp_result_fn callback_fn, void* callback_arg);
err_t smtp_send_mail_static(const char *from, const char* to, const char* subject, const char* body,
smtp_result_fn callback_fn, void* callback_arg);
void smtp_send_mail_int(void *arg);
#ifdef LWIP_DEBUG
const char* smtp_result_str(u8_t smtp_result);
#endif
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SMTP_H */
@@ -0,0 +1,81 @@
#ifndef LWIP_HDR_APPS_SMTP_OPTS_H
#define LWIP_HDR_APPS_SMTP_OPTS_H
#include "lwip/opt.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup smtp_opts Options
* @ingroup smtp
*
* @{
*/
/** Set this to 1 to enable data handler callback on BODY */
#ifndef SMTP_BODYDH
#define SMTP_BODYDH 0
#endif
/** SMTP_DEBUG: Enable debugging for SNTP. */
#ifndef SMTP_DEBUG
#define SMTP_DEBUG LWIP_DBG_OFF
#endif
/** Maximum length reserved for server name including terminating 0 byte */
#ifndef SMTP_MAX_SERVERNAME_LEN
#define SMTP_MAX_SERVERNAME_LEN 256
#endif
/** Maximum length reserved for username */
#ifndef SMTP_MAX_USERNAME_LEN
#define SMTP_MAX_USERNAME_LEN 32
#endif
/** Maximum length reserved for password */
#ifndef SMTP_MAX_PASS_LEN
#define SMTP_MAX_PASS_LEN 32
#endif
/** Set this to 0 if you know the authentication data will not change
* during the smtp session, which saves some heap space. */
#ifndef SMTP_COPY_AUTHDATA
#define SMTP_COPY_AUTHDATA 1
#endif
/** Set this to 0 to save some code space if you know for sure that all data
* passed to this module conforms to the requirements in the SMTP RFC.
* WARNING: use this with care!
*/
#ifndef SMTP_CHECK_DATA
#define SMTP_CHECK_DATA 1
#endif
/** Set this to 1 to enable AUTH PLAIN support */
#ifndef SMTP_SUPPORT_AUTH_PLAIN
#define SMTP_SUPPORT_AUTH_PLAIN 1
#endif
/** Set this to 1 to enable AUTH LOGIN support */
#ifndef SMTP_SUPPORT_AUTH_LOGIN
#define SMTP_SUPPORT_AUTH_LOGIN 1
#endif
/* Memory allocation/deallocation can be overridden... */
#ifndef SMTP_STATE_MALLOC
#define SMTP_STATE_MALLOC(size) mem_malloc(size)
#define SMTP_STATE_FREE(ptr) mem_free(ptr)
#endif
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* SMTP_OPTS_H */
@@ -0,0 +1,135 @@
/**
* @file
* SNMP server main API - start and basic configuration
*/
/*
* Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv>
* Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Leon Woestenberg <leon.woestenberg@axon.tv>
* Martin Hentschel <info@cl-soft.de>
*
*/
#ifndef LWIP_HDR_APPS_SNMP_H
#define LWIP_HDR_APPS_SNMP_H
#include "lwip/apps/snmp_opts.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/err.h"
#include "lwip/apps/snmp_core.h"
/** SNMP variable binding descriptor (publically needed for traps) */
struct snmp_varbind
{
/** pointer to next varbind, NULL for last in list */
struct snmp_varbind *next;
/** pointer to previous varbind, NULL for first in list */
struct snmp_varbind *prev;
/** object identifier */
struct snmp_obj_id oid;
/** value ASN1 type */
u8_t type;
/** object value length */
u16_t value_len;
/** object value */
void *value;
};
/**
* @ingroup snmp_core
* Agent setup, start listening to port 161.
*/
void snmp_init(void);
void snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs);
void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid);
const struct snmp_obj_id* snmp_get_device_enterprise_oid(void);
void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable);
void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst);
/** Generic trap: cold start */
#define SNMP_GENTRAP_COLDSTART 0
/** Generic trap: warm start */
#define SNMP_GENTRAP_WARMSTART 1
/** Generic trap: link down */
#define SNMP_GENTRAP_LINKDOWN 2
/** Generic trap: link up */
#define SNMP_GENTRAP_LINKUP 3
/** Generic trap: authentication failure */
#define SNMP_GENTRAP_AUTH_FAILURE 4
/** Generic trap: EGP neighbor lost */
#define SNMP_GENTRAP_EGP_NEIGHBOR_LOSS 5
/** Generic trap: enterprise specific */
#define SNMP_GENTRAP_ENTERPRISE_SPECIFIC 6
err_t snmp_send_trap_generic(s32_t generic_trap);
err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds);
err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds);
#define SNMP_AUTH_TRAPS_DISABLED 0
#define SNMP_AUTH_TRAPS_ENABLED 1
void snmp_set_auth_traps_enabled(u8_t enable);
u8_t snmp_get_auth_traps_enabled(void);
u8_t snmp_v1_enabled(void);
u8_t snmp_v2c_enabled(void);
u8_t snmp_v3_enabled(void);
void snmp_v1_enable(u8_t enable);
void snmp_v2c_enable(u8_t enable);
void snmp_v3_enable(u8_t enable);
const char * snmp_get_community(void);
const char * snmp_get_community_write(void);
const char * snmp_get_community_trap(void);
void snmp_set_community(const char * const community);
void snmp_set_community_write(const char * const community);
void snmp_set_community_trap(const char * const community);
void snmp_coldstart_trap(void);
void snmp_authfail_trap(void);
typedef void (*snmp_write_callback_fct)(const u32_t* oid, u8_t oid_len, void* callback_arg);
void snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg);
#endif /* LWIP_SNMP */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SNMP_H */
@@ -0,0 +1,377 @@
/**
* @file
* SNMP core API for implementing MIBs
*/
/*
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Christiaan Simons <christiaan.simons@axon.tv>
* Martin Hentschel <info@cl-soft.de>
*/
#ifndef LWIP_HDR_APPS_SNMP_CORE_H
#define LWIP_HDR_APPS_SNMP_CORE_H
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/ip_addr.h"
#include "lwip/err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* basic ASN1 defines */
#define SNMP_ASN1_CLASS_UNIVERSAL 0x00
#define SNMP_ASN1_CLASS_APPLICATION 0x40
#define SNMP_ASN1_CLASS_CONTEXT 0x80
#define SNMP_ASN1_CLASS_PRIVATE 0xC0
#define SNMP_ASN1_CONTENTTYPE_PRIMITIVE 0x00
#define SNMP_ASN1_CONTENTTYPE_CONSTRUCTED 0x20
/* universal tags (from ASN.1 spec.) */
#define SNMP_ASN1_UNIVERSAL_END_OF_CONTENT 0
#define SNMP_ASN1_UNIVERSAL_INTEGER 2
#define SNMP_ASN1_UNIVERSAL_OCTET_STRING 4
#define SNMP_ASN1_UNIVERSAL_NULL 5
#define SNMP_ASN1_UNIVERSAL_OBJECT_ID 6
#define SNMP_ASN1_UNIVERSAL_SEQUENCE_OF 16
/* application specific (SNMP) tags (from SNMPv2-SMI) */
#define SNMP_ASN1_APPLICATION_IPADDR 0 /* [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) */
#define SNMP_ASN1_APPLICATION_COUNTER 1 /* [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) => u32_t */
#define SNMP_ASN1_APPLICATION_GAUGE 2 /* [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) => u32_t */
#define SNMP_ASN1_APPLICATION_TIMETICKS 3 /* [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) => u32_t */
#define SNMP_ASN1_APPLICATION_OPAQUE 4 /* [APPLICATION 4] IMPLICIT OCTET STRING */
#define SNMP_ASN1_APPLICATION_COUNTER64 6 /* [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) */
/* context specific (SNMP) tags (from RFC 1905) */
#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE 1
/* full ASN1 type defines */
#define SNMP_ASN1_TYPE_END_OF_CONTENT (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_END_OF_CONTENT)
#define SNMP_ASN1_TYPE_INTEGER (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_INTEGER)
#define SNMP_ASN1_TYPE_OCTET_STRING (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OCTET_STRING)
#define SNMP_ASN1_TYPE_NULL (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_NULL)
#define SNMP_ASN1_TYPE_OBJECT_ID (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OBJECT_ID)
#define SNMP_ASN1_TYPE_SEQUENCE (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_UNIVERSAL_SEQUENCE_OF)
#define SNMP_ASN1_TYPE_IPADDR (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_IPADDR)
#define SNMP_ASN1_TYPE_IPADDRESS SNMP_ASN1_TYPE_IPADDR
#define SNMP_ASN1_TYPE_COUNTER (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER)
#define SNMP_ASN1_TYPE_COUNTER32 SNMP_ASN1_TYPE_COUNTER
#define SNMP_ASN1_TYPE_GAUGE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_GAUGE)
#define SNMP_ASN1_TYPE_GAUGE32 SNMP_ASN1_TYPE_GAUGE
#define SNMP_ASN1_TYPE_UNSIGNED32 SNMP_ASN1_TYPE_GAUGE
#define SNMP_ASN1_TYPE_TIMETICKS (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_TIMETICKS)
#define SNMP_ASN1_TYPE_OPAQUE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_OPAQUE)
#if LWIP_HAVE_INT64
#define SNMP_ASN1_TYPE_COUNTER64 (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER64)
#endif
#define SNMP_VARBIND_EXCEPTION_OFFSET 0xF0
#define SNMP_VARBIND_EXCEPTION_MASK 0x0F
/** error codes predefined by SNMP prot. */
typedef enum {
SNMP_ERR_NOERROR = 0,
/*
outdated v1 error codes. do not use anmore!
#define SNMP_ERR_NOSUCHNAME 2 use SNMP_ERR_NOSUCHINSTANCE instead
#define SNMP_ERR_BADVALUE 3 use SNMP_ERR_WRONGTYPE,SNMP_ERR_WRONGLENGTH,SNMP_ERR_WRONGENCODING or SNMP_ERR_WRONGVALUE instead
#define SNMP_ERR_READONLY 4 use SNMP_ERR_NOTWRITABLE instead
*/
SNMP_ERR_GENERROR = 5,
SNMP_ERR_NOACCESS = 6,
SNMP_ERR_WRONGTYPE = 7,
SNMP_ERR_WRONGLENGTH = 8,
SNMP_ERR_WRONGENCODING = 9,
SNMP_ERR_WRONGVALUE = 10,
SNMP_ERR_NOCREATION = 11,
SNMP_ERR_INCONSISTENTVALUE = 12,
SNMP_ERR_RESOURCEUNAVAILABLE = 13,
SNMP_ERR_COMMITFAILED = 14,
SNMP_ERR_UNDOFAILED = 15,
SNMP_ERR_NOTWRITABLE = 17,
SNMP_ERR_INCONSISTENTNAME = 18,
SNMP_ERR_NOSUCHINSTANCE = SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE
} snmp_err_t;
/** internal object identifier representation */
struct snmp_obj_id
{
u8_t len;
u32_t id[SNMP_MAX_OBJ_ID_LEN];
};
struct snmp_obj_id_const_ref
{
u8_t len;
const u32_t* id;
};
extern const struct snmp_obj_id_const_ref snmp_zero_dot_zero; /* administrative identifier from SNMPv2-SMI */
/** SNMP variant value, used as reference in struct snmp_node_instance and table implementation */
union snmp_variant_value
{
void* ptr;
const void* const_ptr;
u32_t u32;
s32_t s32;
#if LWIP_HAVE_INT64
u64_t u64;
#endif
};
/**
SNMP MIB node types
tree node is the only node the stack can process in order to walk the tree,
all other nodes are assumed to be leaf nodes.
This cannot be an enum because users may want to define their own node types.
*/
#define SNMP_NODE_TREE 0x00
/* predefined leaf node types */
#define SNMP_NODE_SCALAR 0x01
#define SNMP_NODE_SCALAR_ARRAY 0x02
#define SNMP_NODE_TABLE 0x03
#define SNMP_NODE_THREADSYNC 0x04
/** node "base class" layout, the mandatory fields for a node */
struct snmp_node
{
/** one out of SNMP_NODE_TREE or any leaf node type (like SNMP_NODE_SCALAR) */
u8_t node_type;
/** the number assigned to this node which used as part of the full OID */
u32_t oid;
};
/** SNMP node instance access types */
typedef enum {
SNMP_NODE_INSTANCE_ACCESS_READ = 1,
SNMP_NODE_INSTANCE_ACCESS_WRITE = 2,
SNMP_NODE_INSTANCE_READ_ONLY = SNMP_NODE_INSTANCE_ACCESS_READ,
SNMP_NODE_INSTANCE_READ_WRITE = (SNMP_NODE_INSTANCE_ACCESS_READ | SNMP_NODE_INSTANCE_ACCESS_WRITE),
SNMP_NODE_INSTANCE_WRITE_ONLY = SNMP_NODE_INSTANCE_ACCESS_WRITE,
SNMP_NODE_INSTANCE_NOT_ACCESSIBLE = 0
} snmp_access_t;
struct snmp_node_instance;
typedef s16_t (*node_instance_get_value_method)(struct snmp_node_instance*, void*);
typedef snmp_err_t (*node_instance_set_test_method)(struct snmp_node_instance*, u16_t, void*);
typedef snmp_err_t (*node_instance_set_value_method)(struct snmp_node_instance*, u16_t, void*);
typedef void (*node_instance_release_method)(struct snmp_node_instance*);
#define SNMP_GET_VALUE_RAW_DATA 0x4000 /* do not use 0x8000 because return value of node_instance_get_value_method is signed16 and 0x8000 would be the signed bit */
/** SNMP node instance */
struct snmp_node_instance
{
/** prefilled with the node, get_instance() is called on; may be changed by user to any value to pass an arbitrary node between calls to get_instance() and get_value/test_value/set_value */
const struct snmp_node* node;
/** prefilled with the instance id requested; for get_instance() this is the exact oid requested; for get_next_instance() this is the relative starting point, stack expects relative oid of next node here */
struct snmp_obj_id instance_oid;
/** ASN type for this object (see snmp_asn1.h for definitions) */
u8_t asn1_type;
/** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */
snmp_access_t access;
/** returns object value for the given object identifier. Return values <0 to indicate an error */
node_instance_get_value_method get_value;
/** tests length and/or range BEFORE setting */
node_instance_set_test_method set_test;
/** sets object value, only called when set_test() was successful */
node_instance_set_value_method set_value;
/** called in any case when the instance is not required anymore by stack (useful for freeing memory allocated in get_instance/get_next_instance methods) */
node_instance_release_method release_instance;
/** reference to pass arbitrary value between calls to get_instance() and get_value/test_value/set_value */
union snmp_variant_value reference;
/** see reference (if reference is a pointer, the length of underlying data may be stored here or anything else) */
u32_t reference_len;
};
/** SNMP tree node */
struct snmp_tree_node
{
/** inherited "base class" members */
struct snmp_node node;
u16_t subnode_count;
const struct snmp_node* const *subnodes;
};
#define SNMP_CREATE_TREE_NODE(oid, subnodes) \
{{ SNMP_NODE_TREE, (oid) }, \
(u16_t)LWIP_ARRAYSIZE(subnodes), (subnodes) }
#define SNMP_CREATE_EMPTY_TREE_NODE(oid) \
{{ SNMP_NODE_TREE, (oid) }, \
0, NULL }
/** SNMP leaf node */
struct snmp_leaf_node
{
/** inherited "base class" members */
struct snmp_node node;
snmp_err_t (*get_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
snmp_err_t (*get_next_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
};
/** represents a single mib with its base oid and root node */
struct snmp_mib
{
const u32_t *base_oid;
u8_t base_oid_len;
const struct snmp_node *root_node;
};
#define SNMP_MIB_CREATE(oid_list, root_node) { (oid_list), (u8_t)LWIP_ARRAYSIZE(oid_list), root_node }
/** OID range structure */
struct snmp_oid_range
{
u32_t min;
u32_t max;
};
/** checks if incoming OID length and values are in allowed ranges */
u8_t snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len);
typedef enum {
SNMP_NEXT_OID_STATUS_SUCCESS,
SNMP_NEXT_OID_STATUS_NO_MATCH,
SNMP_NEXT_OID_STATUS_BUF_TO_SMALL
} snmp_next_oid_status_t;
/** state for next_oid_init / next_oid_check functions */
struct snmp_next_oid_state
{
const u32_t* start_oid;
u8_t start_oid_len;
u32_t* next_oid;
u8_t next_oid_len;
u8_t next_oid_max_len;
snmp_next_oid_status_t status;
void* reference;
};
void snmp_next_oid_init(struct snmp_next_oid_state *state,
const u32_t *start_oid, u8_t start_oid_len,
u32_t *next_oid_buf, u8_t next_oid_max_len);
u8_t snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, u8_t oid_len);
u8_t snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, u8_t oid_len, void* reference);
void snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len);
void snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len);
void snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len);
void snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len);
u8_t snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len);
s8_t snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len);
#if LWIP_IPV4
u8_t snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip);
void snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid);
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
u8_t snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip);
void snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid);
#endif /* LWIP_IPV6 */
#if LWIP_IPV4 || LWIP_IPV6
u8_t snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid);
u8_t snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid);
u8_t snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip);
u8_t snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port);
#endif /* LWIP_IPV4 || LWIP_IPV6 */
struct netif;
u8_t netif_to_num(const struct netif *netif);
snmp_err_t snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value); /* generic function which can be used if test is always successful */
err_t snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value);
err_t snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value);
u8_t snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count);
u8_t snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value);
struct snmp_statistics
{
u32_t inpkts;
u32_t outpkts;
u32_t inbadversions;
u32_t inbadcommunitynames;
u32_t inbadcommunityuses;
u32_t inasnparseerrs;
u32_t intoobigs;
u32_t innosuchnames;
u32_t inbadvalues;
u32_t inreadonlys;
u32_t ingenerrs;
u32_t intotalreqvars;
u32_t intotalsetvars;
u32_t ingetrequests;
u32_t ingetnexts;
u32_t insetrequests;
u32_t ingetresponses;
u32_t intraps;
u32_t outtoobigs;
u32_t outnosuchnames;
u32_t outbadvalues;
u32_t outgenerrs;
u32_t outgetrequests;
u32_t outgetnexts;
u32_t outsetrequests;
u32_t outgetresponses;
u32_t outtraps;
#if LWIP_SNMP_V3
u32_t unsupportedseclevels;
u32_t notintimewindows;
u32_t unknownusernames;
u32_t unknownengineids;
u32_t wrongdigests;
u32_t decryptionerrors;
#endif
};
extern struct snmp_statistics snmp_stats;
#ifdef __cplusplus
}
#endif
#endif /* LWIP_SNMP */
#endif /* LWIP_HDR_APPS_SNMP_CORE_H */
@@ -0,0 +1,78 @@
/**
* @file
* SNMP MIB2 API
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
*
*/
#ifndef LWIP_HDR_APPS_SNMP_MIB2_H
#define LWIP_HDR_APPS_SNMP_MIB2_H
#include "lwip/apps/snmp_opts.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#if SNMP_LWIP_MIB2
#include "lwip/apps/snmp_core.h"
extern const struct snmp_mib mib2;
#if SNMP_USE_NETCONN
#include "lwip/apps/snmp_threadsync.h"
void snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg);
extern struct snmp_threadsync_instance snmp_mib2_lwip_locks;
#endif
#ifndef SNMP_SYSSERVICES
#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2))
#endif
void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be defintion */
void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize);
void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen);
void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize);
void snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen);
void snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize);
void snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen);
#endif /* SNMP_LWIP_MIB2 */
#endif /* LWIP_SNMP */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SNMP_MIB2_H */
@@ -0,0 +1,297 @@
/**
* @file
* SNMP server options list
*/
/*
* Copyright (c) 2015 Dirk Ziegelmeier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Dirk Ziegelmeier
*
*/
#ifndef LWIP_HDR_SNMP_OPTS_H
#define LWIP_HDR_SNMP_OPTS_H
#include "lwip/opt.h"
/**
* @defgroup snmp_opts Options
* @ingroup snmp
* @{
*/
/**
* LWIP_SNMP==1: This enables the lwIP SNMP agent. UDP must be available
* for SNMP transport.
* If you want to use your own SNMP agent, leave this disabled.
* To integrate MIB2 of an external agent, you need to enable
* LWIP_MIB2_CALLBACKS and MIB2_STATS. This will give you the callbacks
* and statistics counters you need to get MIB2 working.
*/
#if !defined LWIP_SNMP || defined __DOXYGEN__
#define LWIP_SNMP 0
#endif
/**
* SNMP_USE_NETCONN: Use netconn API instead of raw API.
* Makes SNMP agent run in a worker thread, so blocking operations
* can be done in MIB calls.
*/
#if !defined SNMP_USE_NETCONN || defined __DOXYGEN__
#define SNMP_USE_NETCONN 0
#endif
/**
* SNMP_USE_RAW: Use raw API.
* SNMP agent does not run in a worker thread, so blocking operations
* should not be done in MIB calls.
*/
#if !defined SNMP_USE_RAW || defined __DOXYGEN__
#define SNMP_USE_RAW 1
#endif
#if SNMP_USE_NETCONN && SNMP_USE_RAW
#error SNMP stack can use only one of the APIs {raw, netconn}
#endif
#if LWIP_SNMP && !SNMP_USE_NETCONN && !SNMP_USE_RAW
#error SNMP stack needs a receive API and UDP {raw, netconn}
#endif
#if SNMP_USE_NETCONN
/**
* SNMP_STACK_SIZE: Stack size of SNMP netconn worker thread
*/
#if !defined SNMP_STACK_SIZE || defined __DOXYGEN__
#define SNMP_STACK_SIZE DEFAULT_THREAD_STACKSIZE
#endif
/**
* SNMP_THREAD_PRIO: SNMP netconn worker thread priority
*/
#if !defined SNMP_THREAD_PRIO || defined __DOXYGEN__
#define SNMP_THREAD_PRIO DEFAULT_THREAD_PRIO
#endif
#endif /* SNMP_USE_NETCONN */
/**
* SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap
* destination is required
*/
#if !defined SNMP_TRAP_DESTINATIONS || defined __DOXYGEN__
#define SNMP_TRAP_DESTINATIONS 1
#endif
/**
* Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not
* a safe action and disabled when SNMP_SAFE_REQUESTS = 1).
* Unsafe requests are disabled by default!
*/
#if !defined SNMP_SAFE_REQUESTS || defined __DOXYGEN__
#define SNMP_SAFE_REQUESTS 1
#endif
/**
* The maximum length of strings used.
*/
#if !defined SNMP_MAX_OCTET_STRING_LEN || defined __DOXYGEN__
#define SNMP_MAX_OCTET_STRING_LEN 127
#endif
/**
* The maximum number of Sub ID's inside an object identifier.
* Indirectly this also limits the maximum depth of SNMP tree.
*/
#if !defined SNMP_MAX_OBJ_ID_LEN || defined __DOXYGEN__
#define SNMP_MAX_OBJ_ID_LEN 50
#endif
#if !defined SNMP_MAX_VALUE_SIZE || defined __DOXYGEN__
/**
* The minimum size of a value.
*/
#define SNMP_MIN_VALUE_SIZE (2 * sizeof(u32_t*)) /* size required to store the basic types (8 bytes for counter64) */
/**
* The maximum size of a value.
*/
#define SNMP_MAX_VALUE_SIZE LWIP_MAX(LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN), sizeof(u32_t)*(SNMP_MAX_OBJ_ID_LEN)), SNMP_MIN_VALUE_SIZE)
#endif
/**
* The snmp read-access community. Used for write-access and traps, too
* unless SNMP_COMMUNITY_WRITE or SNMP_COMMUNITY_TRAP are enabled, respectively.
*/
#if !defined SNMP_COMMUNITY || defined __DOXYGEN__
#define SNMP_COMMUNITY "public"
#endif
/**
* The snmp write-access community.
* Set this community to "" in order to disallow any write access.
*/
#if !defined SNMP_COMMUNITY_WRITE || defined __DOXYGEN__
#define SNMP_COMMUNITY_WRITE "private"
#endif
/**
* The snmp community used for sending traps.
*/
#if !defined SNMP_COMMUNITY_TRAP || defined __DOXYGEN__
#define SNMP_COMMUNITY_TRAP "public"
#endif
/**
* The maximum length of community string.
* If community names shall be adjusted at runtime via snmp_set_community() calls,
* enter here the possible maximum length (+1 for terminating null character).
*/
#if !defined SNMP_MAX_COMMUNITY_STR_LEN || defined __DOXYGEN__
#define SNMP_MAX_COMMUNITY_STR_LEN LWIP_MAX(LWIP_MAX(sizeof(SNMP_COMMUNITY), sizeof(SNMP_COMMUNITY_WRITE)), sizeof(SNMP_COMMUNITY_TRAP))
#endif
/**
* The OID identifiying the device. This may be the enterprise OID itself or any OID located below it in tree.
*/
#if !defined SNMP_DEVICE_ENTERPRISE_OID || defined __DOXYGEN__
#define SNMP_LWIP_ENTERPRISE_OID 26381
/**
* IANA assigned enterprise ID for lwIP is 26381
* @see http://www.iana.org/assignments/enterprise-numbers
*
* @note this enterprise ID is assigned to the lwIP project,
* all object identifiers living under this ID are assigned
* by the lwIP maintainers!
* @note don't change this define, use snmp_set_device_enterprise_oid()
*
* If you need to create your own private MIB you'll need
* to apply for your own enterprise ID with IANA:
* http://www.iana.org/numbers.html
*/
#define SNMP_DEVICE_ENTERPRISE_OID {1, 3, 6, 1, 4, 1, SNMP_LWIP_ENTERPRISE_OID}
/**
* Length of SNMP_DEVICE_ENTERPRISE_OID
*/
#define SNMP_DEVICE_ENTERPRISE_OID_LEN 7
#endif
/**
* SNMP_DEBUG: Enable debugging for SNMP messages.
*/
#if !defined SNMP_DEBUG || defined __DOXYGEN__
#define SNMP_DEBUG LWIP_DBG_OFF
#endif
/**
* SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs.
*/
#if !defined SNMP_MIB_DEBUG || defined __DOXYGEN__
#define SNMP_MIB_DEBUG LWIP_DBG_OFF
#endif
/**
* Indicates if the MIB2 implementation of LWIP SNMP stack is used.
*/
#if !defined SNMP_LWIP_MIB2 || defined __DOXYGEN__
#define SNMP_LWIP_MIB2 LWIP_SNMP
#endif
/**
* Value return for sysDesc field of MIB2.
*/
#if !defined SNMP_LWIP_MIB2_SYSDESC || defined __DOXYGEN__
#define SNMP_LWIP_MIB2_SYSDESC "lwIP"
#endif
/**
* Value return for sysName field of MIB2.
* To make sysName field settable, call snmp_mib2_set_sysname() to provide the necessary buffers.
*/
#if !defined SNMP_LWIP_MIB2_SYSNAME || defined __DOXYGEN__
#define SNMP_LWIP_MIB2_SYSNAME "FQDN-unk"
#endif
/**
* Value return for sysContact field of MIB2.
* To make sysContact field settable, call snmp_mib2_set_syscontact() to provide the necessary buffers.
*/
#if !defined SNMP_LWIP_MIB2_SYSCONTACT || defined __DOXYGEN__
#define SNMP_LWIP_MIB2_SYSCONTACT ""
#endif
/**
* Value return for sysLocation field of MIB2.
* To make sysLocation field settable, call snmp_mib2_set_syslocation() to provide the necessary buffers.
*/
#if !defined SNMP_LWIP_MIB2_SYSLOCATION || defined __DOXYGEN__
#define SNMP_LWIP_MIB2_SYSLOCATION ""
#endif
/**
* This value is used to limit the repetitions processed in GetBulk requests (value == 0 means no limitation).
* This may be useful to limit the load for a single request.
* According to SNMP RFC 1905 it is allowed to not return all requested variables from a GetBulk request if system load would be too high.
* so the effect is that the client will do more requests to gather all data.
* For the stack this could be useful in case that SNMP processing is done in TCP/IP thread. In this situation a request with many
* repetitions could block the thread for a longer time. Setting limit here will keep the stack more responsive.
*/
#if !defined SNMP_LWIP_GETBULK_MAX_REPETITIONS || defined __DOXYGEN__
#define SNMP_LWIP_GETBULK_MAX_REPETITIONS 0
#endif
/**
* @}
*/
/*
------------------------------------
---------- SNMPv3 options ----------
------------------------------------
*/
/**
* LWIP_SNMP_V3==1: This enables EXPERIMENTAL SNMPv3 support. LWIP_SNMP must
* also be enabled.
* THIS IS UNDER DEVELOPMENT AND SHOULD NOT BE ENABLED IN PRODUCTS.
*/
#ifndef LWIP_SNMP_V3
#define LWIP_SNMP_V3 0
#endif
#ifndef LWIP_SNMP_V3_MBEDTLS
#define LWIP_SNMP_V3_MBEDTLS LWIP_SNMP_V3
#endif
#ifndef LWIP_SNMP_V3_CRYPTO
#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3_MBEDTLS
#endif
#ifndef LWIP_SNMP_CONFIGURE_VERSIONS
#define LWIP_SNMP_CONFIGURE_VERSIONS 0
#endif
#endif /* LWIP_HDR_SNMP_OPTS_H */
@@ -0,0 +1,113 @@
/**
* @file
* SNMP server MIB API to implement scalar nodes
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel <info@cl-soft.de>
*
*/
#ifndef LWIP_HDR_APPS_SNMP_SCALAR_H
#define LWIP_HDR_APPS_SNMP_SCALAR_H
#include "lwip/apps/snmp_opts.h"
#include "lwip/apps/snmp_core.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
/** basic scalar node */
struct snmp_scalar_node
{
/** inherited "base class" members */
struct snmp_leaf_node node;
u8_t asn1_type;
snmp_access_t access;
node_instance_get_value_method get_value;
node_instance_set_test_method set_test;
node_instance_set_value_method set_value;
};
snmp_err_t snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
snmp_err_t snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
#define SNMP_SCALAR_CREATE_NODE(oid, access, asn1_type, get_value_method, set_test_method, set_value_method) \
{{{ SNMP_NODE_SCALAR, (oid) }, \
snmp_scalar_get_instance, \
snmp_scalar_get_next_instance }, \
(asn1_type), (access), (get_value_method), (set_test_method), (set_value_method) }
#define SNMP_SCALAR_CREATE_NODE_READONLY(oid, asn1_type, get_value_method) SNMP_SCALAR_CREATE_NODE(oid, SNMP_NODE_INSTANCE_READ_ONLY, asn1_type, get_value_method, NULL, NULL)
/** scalar array node - a tree node which contains scalars only as children */
struct snmp_scalar_array_node_def
{
u32_t oid;
u8_t asn1_type;
snmp_access_t access;
};
typedef s16_t (*snmp_scalar_array_get_value_method)(const struct snmp_scalar_array_node_def*, void*);
typedef snmp_err_t (*snmp_scalar_array_set_test_method)(const struct snmp_scalar_array_node_def*, u16_t, void*);
typedef snmp_err_t (*snmp_scalar_array_set_value_method)(const struct snmp_scalar_array_node_def*, u16_t, void*);
/** basic scalar array node */
struct snmp_scalar_array_node
{
/** inherited "base class" members */
struct snmp_leaf_node node;
u16_t array_node_count;
const struct snmp_scalar_array_node_def* array_nodes;
snmp_scalar_array_get_value_method get_value;
snmp_scalar_array_set_test_method set_test;
snmp_scalar_array_set_value_method set_value;
};
snmp_err_t snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
snmp_err_t snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
#define SNMP_SCALAR_CREATE_ARRAY_NODE(oid, array_nodes, get_value_method, set_test_method, set_value_method) \
{{{ SNMP_NODE_SCALAR_ARRAY, (oid) }, \
snmp_scalar_array_get_instance, \
snmp_scalar_array_get_next_instance }, \
(u16_t)LWIP_ARRAYSIZE(array_nodes), (array_nodes), (get_value_method), (set_test_method), (set_value_method) }
#endif /* LWIP_SNMP */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SNMP_SCALAR_H */
@@ -0,0 +1,32 @@
/*
Generated by LwipMibCompiler
*/
#ifndef LWIP_HDR_APPS_SNMP_FRAMEWORK_MIB_H
#define LWIP_HDR_APPS_SNMP_FRAMEWORK_MIB_H
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "lwip/apps/snmp_core.h"
extern const struct snmp_obj_id usmNoAuthProtocol;
extern const struct snmp_obj_id usmHMACMD5AuthProtocol;
extern const struct snmp_obj_id usmHMACSHAAuthProtocol;
extern const struct snmp_obj_id usmNoPrivProtocol;
extern const struct snmp_obj_id usmDESPrivProtocol;
extern const struct snmp_obj_id usmAESPrivProtocol;
extern const struct snmp_mib snmpframeworkmib;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWIP_SNMP */
#endif /* LWIP_HDR_APPS_SNMP_FRAMEWORK_MIB_H */
@@ -0,0 +1,24 @@
/*
Generated by LwipMibCompiler
*/
#ifndef LWIP_HDR_APPS_SNMP_USER_BASED_SM_MIB_H
#define LWIP_HDR_APPS_SNMP_USER_BASED_SM_MIB_H
#include "lwip/apps/snmp_opts.h"
#if LWIP_SNMP
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "lwip/apps/snmp_core.h"
extern const struct snmp_mib snmpusmmib;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWIP_SNMP */
#endif /* LWIP_HDR_APPS_SNMP_USER_BASED_SM_MIB_H */
@@ -0,0 +1,134 @@
/**
* @file
* SNMP server MIB API to implement table nodes
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Martin Hentschel <info@cl-soft.de>
*
*/
#ifndef LWIP_HDR_APPS_SNMP_TABLE_H
#define LWIP_HDR_APPS_SNMP_TABLE_H
#include "lwip/apps/snmp_opts.h"
#include "lwip/apps/snmp_core.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
/** default (customizable) read/write table */
struct snmp_table_col_def
{
u32_t index;
u8_t asn1_type;
snmp_access_t access;
};
/** table node */
struct snmp_table_node
{
/** inherited "base class" members */
struct snmp_leaf_node node;
u16_t column_count;
const struct snmp_table_col_def* columns;
snmp_err_t (*get_cell_instance)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance);
snmp_err_t (*get_next_cell_instance)(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance);
/** returns object value for the given object identifier */
node_instance_get_value_method get_value;
/** tests length and/or range BEFORE setting */
node_instance_set_test_method set_test;
/** sets object value, only called when set_test() was successful */
node_instance_set_value_method set_value;
};
snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
#define SNMP_TABLE_CREATE(oid, columns, get_cell_instance_method, get_next_cell_instance_method, get_value_method, set_test_method, set_value_method) \
{{{ SNMP_NODE_TABLE, (oid) }, \
snmp_table_get_instance, \
snmp_table_get_next_instance }, \
(u16_t)LWIP_ARRAYSIZE(columns), (columns), \
(get_cell_instance_method), (get_next_cell_instance_method), \
(get_value_method), (set_test_method), (set_value_method)}
#define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */
/** simple read-only table */
typedef enum {
SNMP_VARIANT_VALUE_TYPE_U32,
SNMP_VARIANT_VALUE_TYPE_S32,
SNMP_VARIANT_VALUE_TYPE_PTR,
SNMP_VARIANT_VALUE_TYPE_CONST_PTR
} snmp_table_column_data_type_t;
struct snmp_table_simple_col_def
{
u32_t index;
u8_t asn1_type;
snmp_table_column_data_type_t data_type; /* depending of what union member is used to store the value*/
};
/** simple read-only table node */
struct snmp_table_simple_node
{
/* inherited "base class" members */
struct snmp_leaf_node node;
u16_t column_count;
const struct snmp_table_simple_col_def* columns;
snmp_err_t (*get_cell_value)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len);
snmp_err_t (*get_next_cell_instance_and_value)(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len);
};
snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
#define SNMP_TABLE_CREATE_SIMPLE(oid, columns, get_cell_value_method, get_next_cell_instance_and_value_method) \
{{{ SNMP_NODE_TABLE, (oid) }, \
snmp_table_simple_get_instance, \
snmp_table_simple_get_next_instance }, \
(u16_t)LWIP_ARRAYSIZE(columns), (columns), (get_cell_value_method), (get_next_cell_instance_and_value_method) }
s16_t snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value);
s16_t snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value);
s16_t snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value);
#endif /* LWIP_SNMP */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SNMP_TABLE_H */
@@ -0,0 +1,114 @@
/**
* @file
* SNMP server MIB API to implement thread synchronization
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Dirk Ziegelmeier <dziegel@gmx.de>
*
*/
#ifndef LWIP_HDR_APPS_SNMP_THREADSYNC_H
#define LWIP_HDR_APPS_SNMP_THREADSYNC_H
#include "lwip/apps/snmp_opts.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
#include "lwip/apps/snmp_core.h"
#include "lwip/sys.h"
typedef void (*snmp_threadsync_called_fn)(void* arg);
typedef void (*snmp_threadsync_synchronizer_fn)(snmp_threadsync_called_fn fn, void* arg);
/** Thread sync runtime data. For internal usage only. */
struct threadsync_data
{
union {
snmp_err_t err;
s16_t s16;
} retval;
union {
const u32_t *root_oid;
void *value;
} arg1;
union {
u8_t root_oid_len;
u16_t len;
} arg2;
const struct snmp_threadsync_node *threadsync_node;
struct snmp_node_instance proxy_instance;
};
/** Thread sync instance. Needed EXCATLY once for every thread to be synced into. */
struct snmp_threadsync_instance
{
sys_sem_t sem;
sys_mutex_t sem_usage_mutex;
snmp_threadsync_synchronizer_fn sync_fn;
struct threadsync_data data;
};
/** SNMP thread sync proxy leaf node */
struct snmp_threadsync_node
{
/* inherited "base class" members */
struct snmp_leaf_node node;
const struct snmp_leaf_node *target;
struct snmp_threadsync_instance *instance;
};
snmp_err_t snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
snmp_err_t snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance);
/** Create thread sync proxy node */
#define SNMP_CREATE_THREAD_SYNC_NODE(oid, target_leaf_node, threadsync_instance) \
{{{ SNMP_NODE_THREADSYNC, (oid) }, \
snmp_threadsync_get_instance, \
snmp_threadsync_get_next_instance }, \
(target_leaf_node), \
(threadsync_instance) }
/** Create thread sync instance data */
void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn);
#endif /* LWIP_SNMP */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SNMP_THREADSYNC_H */
@@ -0,0 +1,114 @@
/**
* @file
* Additional SNMPv3 functionality RFC3414 and RFC3826.
*/
/*
* Copyright (c) 2016 Elias Oenal.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Elias Oenal <lwip@eliasoenal.com>
*/
#ifndef LWIP_HDR_APPS_SNMP_V3_H
#define LWIP_HDR_APPS_SNMP_V3_H
#include "lwip/apps/snmp_opts.h"
#include "lwip/err.h"
#ifdef __cplusplus
extern "C" {
#endif
#if LWIP_SNMP && LWIP_SNMP_V3
typedef enum
{
SNMP_V3_AUTH_ALGO_INVAL = 0,
SNMP_V3_AUTH_ALGO_MD5 = 1,
SNMP_V3_AUTH_ALGO_SHA = 2
} snmpv3_auth_algo_t;
typedef enum
{
SNMP_V3_PRIV_ALGO_INVAL = 0,
SNMP_V3_PRIV_ALGO_DES = 1,
SNMP_V3_PRIV_ALGO_AES = 2
} snmpv3_priv_algo_t;
typedef enum
{
SNMP_V3_USER_STORAGETYPE_OTHER = 1,
SNMP_V3_USER_STORAGETYPE_VOLATILE = 2,
SNMP_V3_USER_STORAGETYPE_NONVOLATILE = 3,
SNMP_V3_USER_STORAGETYPE_PERMANENT = 4,
SNMP_V3_USER_STORAGETYPE_READONLY = 5
} snmpv3_user_storagetype_t;
/*
* The following callback functions must be implemented by the application.
* There is a dummy implementation in snmpv3_dummy.c.
*/
void snmpv3_get_engine_id(const char **id, u8_t *len);
err_t snmpv3_set_engine_id(const char* id, u8_t len);
u32_t snmpv3_get_engine_boots(void);
void snmpv3_set_engine_boots(u32_t boots);
u32_t snmpv3_get_engine_time(void);
void snmpv3_reset_engine_time(void);
err_t snmpv3_get_user(const char* username, snmpv3_auth_algo_t *auth_algo, u8_t *auth_key, snmpv3_priv_algo_t *priv_algo, u8_t *priv_key);
u8_t snmpv3_get_amount_of_users(void);
err_t snmpv3_get_user_storagetype(const char *username, snmpv3_user_storagetype_t *storagetype);
err_t snmpv3_get_username(char *username, u8_t index);
/* The following functions are provided by the SNMPv3 agent */
void snmpv3_engine_id_changed(void);
s32_t snmpv3_get_engine_time_internal(void);
void snmpv3_password_to_key_md5(
const u8_t *password, /* IN */
size_t passwordlen, /* IN */
const u8_t *engineID, /* IN - pointer to snmpEngineID */
u8_t engineLength, /* IN - length of snmpEngineID */
u8_t *key); /* OUT - pointer to caller 16-octet buffer */
void snmpv3_password_to_key_sha(
const u8_t *password, /* IN */
size_t passwordlen, /* IN */
const u8_t *engineID, /* IN - pointer to snmpEngineID */
u8_t engineLength, /* IN - length of snmpEngineID */
u8_t *key); /* OUT - pointer to caller 20-octet buffer */
#endif
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SNMP_V3_H */
@@ -0,0 +1,80 @@
/**
* @file
* SNTP client API
*/
/*
* Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Frédéric Bernon, Simon Goldschmidt
*
*/
#ifndef LWIP_HDR_APPS_SNTP_H
#define LWIP_HDR_APPS_SNTP_H
#include "lwip/apps/sntp_opts.h"
#include "lwip/ip_addr.h"
#ifdef __cplusplus
extern "C" {
#endif
/* SNTP operating modes: default is to poll using unicast.
The mode has to be set before calling sntp_init(). */
#define SNTP_OPMODE_POLL 0
#define SNTP_OPMODE_LISTENONLY 1
void sntp_setoperatingmode(u8_t operating_mode);
u8_t sntp_getoperatingmode(void);
void sntp_init(void);
void sntp_stop(void);
u8_t sntp_enabled(void);
void sntp_setserver(u8_t idx, const ip_addr_t *addr);
const ip_addr_t* sntp_getserver(u8_t idx);
#if SNTP_MONITOR_SERVER_REACHABILITY
u8_t sntp_getreachability(u8_t idx);
#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
#if SNTP_SERVER_DNS
void sntp_setservername(u8_t idx, const char *server);
const char *sntp_getservername(u8_t idx);
#endif /* SNTP_SERVER_DNS */
#if SNTP_GET_SERVERS_FROM_DHCP
void sntp_servermode_dhcp(int set_servers_from_dhcp);
#else /* SNTP_GET_SERVERS_FROM_DHCP */
#define sntp_servermode_dhcp(x)
#endif /* SNTP_GET_SERVERS_FROM_DHCP */
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_SNTP_H */
@@ -0,0 +1,209 @@
/**
* @file
* SNTP client options list
*/
/*
* Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Frédéric Bernon, Simon Goldschmidt
*
*/
#ifndef LWIP_HDR_APPS_SNTP_OPTS_H
#define LWIP_HDR_APPS_SNTP_OPTS_H
#include "lwip/opt.h"
#include "lwip/prot/iana.h"
/**
* @defgroup sntp_opts Options
* @ingroup sntp
* @{
*/
/** SNTP macro to change system time in seconds
* Define SNTP_SET_SYSTEM_TIME_US(sec, us) to set the time in microseconds
* instead of this one if you need the additional precision. Alternatively,
* define SNTP_SET_SYSTEM_TIME_NTP(sec, frac) in order to work with native
* NTP timestamps instead.
*/
#if !defined SNTP_SET_SYSTEM_TIME || defined __DOXYGEN__
#define SNTP_SET_SYSTEM_TIME(sec) LWIP_UNUSED_ARG(sec)
#endif
/** The maximum number of SNTP servers that can be set */
#if !defined SNTP_MAX_SERVERS || defined __DOXYGEN__
#define SNTP_MAX_SERVERS LWIP_DHCP_MAX_NTP_SERVERS
#endif
/** Set this to 1 to implement the callback function called by dhcp when
* NTP servers are received. */
#if !defined SNTP_GET_SERVERS_FROM_DHCP || defined __DOXYGEN__
#define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV
#endif
/** Set this to 1 to support DNS names (or IP address strings) to set sntp servers
* One server address/name can be defined as default if SNTP_SERVER_DNS == 1:
* \#define SNTP_SERVER_ADDRESS "pool.ntp.org"
*/
#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__
#define SNTP_SERVER_DNS 0
#endif
/**
* SNTP_DEBUG: Enable debugging for SNTP.
*/
#if !defined SNTP_DEBUG || defined __DOXYGEN__
#define SNTP_DEBUG LWIP_DBG_OFF
#endif
/** SNTP server port */
#if !defined SNTP_PORT || defined __DOXYGEN__
#define SNTP_PORT LWIP_IANA_PORT_SNTP
#endif
/** Sanity check:
* Define this to
* - 0 to turn off sanity checks (default; smaller code)
* - >= 1 to check address and port of the response packet to ensure the
* response comes from the server we sent the request to.
* - >= 2 to check returned Originate Timestamp against Transmit Timestamp
* sent to the server (to ensure response to older request).
* - >= 3 @todo: discard reply if any of the VN, Stratum, or Transmit Timestamp
* fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast).
* - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each
* greater than or equal to 0 and less than infinity, where infinity is
* currently a cozy number like one second. This check avoids using a
* server whose synchronization source has expired for a very long time.
*/
#if !defined SNTP_CHECK_RESPONSE || defined __DOXYGEN__
#define SNTP_CHECK_RESPONSE 0
#endif
/** Enable round-trip delay compensation.
* Compensate for the round-trip delay by calculating the clock offset from
* the originate, receive, transmit and destination timestamps, as per RFC.
*
* The calculation requires compiler support for 64-bit integers. Also, either
* SNTP_SET_SYSTEM_TIME_US or SNTP_SET_SYSTEM_TIME_NTP has to be implemented
* for setting the system clock with sub-second precision. Likewise, either
* SNTP_GET_SYSTEM_TIME or SNTP_GET_SYSTEM_TIME_NTP needs to be implemented
* with sub-second precision.
*
* Although not strictly required, it makes sense to combine this option with
* SNTP_CHECK_RESPONSE >= 2 for sanity-checking of the received timestamps.
* Also, in order for the round-trip calculation to work, the difference
* between the local clock and the NTP server clock must not be larger than
* about 34 years. If that limit is exceeded, the implementation will fall back
* to setting the clock without compensation. In order to ensure that the local
* clock is always within the permitted range for compensation, even at first
* try, it may be necessary to store at least the current year in non-volatile
* memory.
*/
#if !defined SNTP_COMP_ROUNDTRIP || defined __DOXYGEN__
#define SNTP_COMP_ROUNDTRIP 0
#endif
/** According to the RFC, this shall be a random delay
* between 1 and 5 minutes (in milliseconds) to prevent load peaks.
* This can be defined to a random generation function,
* which must return the delay in milliseconds as u32_t.
* Turned off by default.
*/
#if !defined SNTP_STARTUP_DELAY || defined __DOXYGEN__
#ifdef LWIP_RAND
#define SNTP_STARTUP_DELAY 1
#else
#define SNTP_STARTUP_DELAY 0
#endif
#endif
/** If you want the startup delay to be a function, define this
* to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1.
*/
#if !defined SNTP_STARTUP_DELAY_FUNC || defined __DOXYGEN__
#define SNTP_STARTUP_DELAY_FUNC (LWIP_RAND() % 5000)
#endif
/** SNTP receive timeout - in milliseconds
* Also used as retry timeout - this shouldn't be too low.
* Default is 15 seconds. Must not be beolw 15 seconds by specification (i.e. 15000)
*/
#if !defined SNTP_RECV_TIMEOUT || defined __DOXYGEN__
#define SNTP_RECV_TIMEOUT 15000
#endif
/** SNTP update delay - in milliseconds
* Default is 1 hour. Must not be beolw 60 seconds by specification (i.e. 60000)
*/
#if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__
#define SNTP_UPDATE_DELAY 3600000
#endif
/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2
* to send in request and compare in response. Also used for round-trip
* delay compensation if SNTP_COMP_ROUNDTRIP != 0.
* Alternatively, define SNTP_GET_SYSTEM_TIME_NTP(sec, frac) in order to
* work with native NTP timestamps instead.
*/
#if !defined SNTP_GET_SYSTEM_TIME || defined __DOXYGEN__
#define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0)
#endif
/** Default retry timeout (in milliseconds) if the response
* received is invalid.
* This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached.
*/
#if !defined SNTP_RETRY_TIMEOUT || defined __DOXYGEN__
#define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT
#endif
/** Maximum retry timeout (in milliseconds). */
#if !defined SNTP_RETRY_TIMEOUT_MAX || defined __DOXYGEN__
#define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10)
#endif
/** Increase retry timeout with every retry sent
* Default is on to conform to RFC.
*/
#if !defined SNTP_RETRY_TIMEOUT_EXP || defined __DOXYGEN__
#define SNTP_RETRY_TIMEOUT_EXP 1
#endif
/** Keep a reachability shift register per server
* Default is on to conform to RFC.
*/
#if !defined SNTP_MONITOR_SERVER_REACHABILITY || defined __DOXYGEN__
#define SNTP_MONITOR_SERVER_REACHABILITY 1
#endif
/**
* @}
*/
#endif /* LWIP_HDR_APPS_SNTP_OPTS_H */
@@ -0,0 +1,106 @@
/**
*
* @file tftp_opts.h
*
* @author Logan Gunthorpe <logang@deltatee.com>
*
* @brief Trivial File Transfer Protocol (RFC 1350) implementation options
*
* Copyright (c) Deltatee Enterprises Ltd. 2013
* All rights reserved.
*
*/
/*
* Redistribution and use in source and binary forms, with or without
* modification,are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Logan Gunthorpe <logang@deltatee.com>
*
*/
#ifndef LWIP_HDR_APPS_TFTP_OPTS_H
#define LWIP_HDR_APPS_TFTP_OPTS_H
#include "lwip/opt.h"
#include "lwip/prot/iana.h"
/**
* @defgroup tftp_opts Options
* @ingroup tftp
* @{
*/
/**
* Enable TFTP debug messages
*/
#if !defined TFTP_DEBUG || defined __DOXYGEN__
#define TFTP_DEBUG LWIP_DBG_OFF
#endif
/**
* TFTP server port
*/
#if !defined TFTP_PORT || defined __DOXYGEN__
#define TFTP_PORT LWIP_IANA_PORT_TFTP
#endif
/**
* TFTP timeout
*/
#if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__
#define TFTP_TIMEOUT_MSECS 10000
#endif
/**
* Max. number of retries when a file is read from server
*/
#if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__
#define TFTP_MAX_RETRIES 5
#endif
/**
* TFTP timer cyclic interval
*/
#if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__
#define TFTP_TIMER_MSECS (TFTP_TIMEOUT_MSECS / 10)
#endif
/**
* Max. length of TFTP filename
*/
#if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__
#define TFTP_MAX_FILENAME_LEN 20
#endif
/**
* Max. length of TFTP mode
*/
#if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__
#define TFTP_MAX_MODE_LEN 7
#endif
/**
* @}
*/
#endif /* LWIP_HDR_APPS_TFTP_OPTS_H */
@@ -0,0 +1,95 @@
/**
*
* @file tftp_server.h
*
* @author Logan Gunthorpe <logang@deltatee.com>
*
* @brief Trivial File Transfer Protocol (RFC 1350)
*
* Copyright (c) Deltatee Enterprises Ltd. 2013
* All rights reserved.
*
*/
/*
* Redistribution and use in source and binary forms, with or without
* modification,are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Logan Gunthorpe <logang@deltatee.com>
*
*/
#ifndef LWIP_HDR_APPS_TFTP_SERVER_H
#define LWIP_HDR_APPS_TFTP_SERVER_H
#include "lwip/apps/tftp_opts.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @ingroup tftp
* TFTP context containing callback functions for TFTP transfers
*/
struct tftp_context {
/**
* Open file for read/write.
* @param fname Filename
* @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail)
* @param write Flag indicating read (0) or write (!= 0) access
* @returns File handle supplied to other functions
*/
void* (*open)(const char* fname, const char* mode, u8_t write);
/**
* Close file handle
* @param handle File handle returned by open()
*/
void (*close)(void* handle);
/**
* Read from file
* @param handle File handle returned by open()
* @param buf Target buffer to copy read data to
* @param bytes Number of bytes to copy to buf
* @returns &gt;= 0: Success; &lt; 0: Error
*/
int (*read)(void* handle, void* buf, int bytes);
/**
* Write to file
* @param handle File handle returned by open()
* @param pbuf PBUF adjusted such that payload pointer points
* to the beginning of write data. In other words,
* TFTP headers are stripped off.
* @returns &gt;= 0: Success; &lt; 0: Error
*/
int (*write)(void* handle, struct pbuf* p);
};
err_t tftp_init(const struct tftp_context* ctx);
void tftp_cleanup(void);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_APPS_TFTP_SERVER_H */
@@ -0,0 +1,393 @@
/**
* @file
* Support for different processor and compiler architectures
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_ARCH_H
#define LWIP_HDR_ARCH_H
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
#include "arch/cc.h"
/**
* @defgroup compiler_abstraction Compiler/platform abstraction
* @ingroup sys_layer
* All defines related to this section must not be placed in lwipopts.h,
* but in arch/cc.h!
* If the compiler does not provide memset() this file must include a
* definition of it, or include a file which defines it.
* These options cannot be \#defined in lwipopts.h since they are not options
* of lwIP itself, but options of the lwIP port to your system.
* @{
*/
/** Define the byte order of the system.
* Needed for conversion of network data to host byte order.
* Allowed values: LITTLE_ENDIAN and BIG_ENDIAN
*/
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
/** Define random number generator function of your system */
#ifdef __DOXYGEN__
#define LWIP_RAND() ((u32_t)rand())
#endif
/** Platform specific diagnostic output.\n
* Note the default implementation pulls in printf, which may
* in turn pull in a lot of standard libary code. In resource-constrained
* systems, this should be defined to something less resource-consuming.
*/
#ifndef LWIP_PLATFORM_DIAG
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#include <stdio.h>
#include <stdlib.h>
#endif
/** Platform specific assertion handling.\n
* Note the default implementation pulls in printf, fflush and abort, which may
* in turn pull in a lot of standard libary code. In resource-constrained
* systems, this should be defined to something less resource-consuming.
*/
#ifndef LWIP_PLATFORM_ASSERT
#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
#include <stdio.h>
#include <stdlib.h>
#endif
/** Define this to 1 in arch/cc.h of your port if you do not want to
* include stddef.h header to get size_t. You need to typedef size_t
* by yourself in this case.
*/
#ifndef LWIP_NO_STDDEF_H
#define LWIP_NO_STDDEF_H 0
#endif
#if !LWIP_NO_STDDEF_H
#include <stddef.h> /* for size_t */
#endif
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the stdint.h header. You need to typedef the generic types listed in
* lwip/arch.h yourself in this case (u8_t, u16_t...).
*/
#ifndef LWIP_NO_STDINT_H
#define LWIP_NO_STDINT_H 0
#endif
/* Define generic types used in lwIP */
#if !LWIP_NO_STDINT_H
#include <stdint.h>
/* stdint.h is C99 which should also provide support for 64-bit integers */
#if !defined(LWIP_HAVE_INT64) && defined(UINT64_MAX)
#define LWIP_HAVE_INT64 1
#endif
typedef uint8_t u8_t;
typedef int8_t s8_t;
typedef uint16_t u16_t;
typedef int16_t s16_t;
typedef uint32_t u32_t;
typedef int32_t s32_t;
#if LWIP_HAVE_INT64
typedef uint64_t u64_t;
typedef int64_t s64_t;
#endif
typedef uintptr_t mem_ptr_t;
#endif
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the inttypes.h header. You need to define the format strings listed in
* lwip/arch.h yourself in this case (X8_F, U16_F...).
*/
#ifndef LWIP_NO_INTTYPES_H
#define LWIP_NO_INTTYPES_H 0
#endif
/* Define (sn)printf formatters for these lwIP types */
#if !LWIP_NO_INTTYPES_H
#include <inttypes.h>
#ifndef X8_F
#define X8_F "02" PRIx8
#endif
#ifndef U16_F
#define U16_F PRIu16
#endif
#ifndef S16_F
#define S16_F PRId16
#endif
#ifndef X16_F
#define X16_F PRIx16
#endif
#ifndef U32_F
#define U32_F PRIu32
#endif
#ifndef S32_F
#define S32_F PRId32
#endif
#ifndef X32_F
#define X32_F PRIx32
#endif
#ifndef SZT_F
#define SZT_F PRIuPTR
#endif
#endif
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the limits.h header. You need to define the type limits yourself in this case
* (e.g. INT_MAX, SSIZE_MAX).
*/
#ifndef LWIP_NO_LIMITS_H
#define LWIP_NO_LIMITS_H 0
#endif
/* Include limits.h? */
#if !LWIP_NO_LIMITS_H
#include <limits.h>
#endif
/* Do we need to define ssize_t? This is a compatibility hack:
* Unfortunately, this type seems to be unavailable on some systems (even if
* sys/types or unistd.h are available).
* Being like that, we define it to 'int' if SSIZE_MAX is not defined.
*/
#ifdef SSIZE_MAX
/* If SSIZE_MAX is defined, unistd.h should provide the type as well */
#ifndef LWIP_NO_UNISTD_H
#define LWIP_NO_UNISTD_H 0
#endif
#if !LWIP_NO_UNISTD_H
#include <unistd.h>
#endif
#else /* SSIZE_MAX */
typedef int ssize_t;
#define SSIZE_MAX INT_MAX
#endif /* SSIZE_MAX */
/* some maximum values needed in lwip code */
#define LWIP_UINT32_MAX 0xffffffff
/** Define this to 1 in arch/cc.h of your port if your compiler does not provide
* the ctype.h header. If ctype.h is available, a few character functions
* are mapped to the appropriate functions (lwip_islower, lwip_isdigit...), if
* not, a private implementation is provided.
*/
#ifndef LWIP_NO_CTYPE_H
#define LWIP_NO_CTYPE_H 0
#endif
#if LWIP_NO_CTYPE_H
#define lwip_in_range(c, lo, up) ((u8_t)(c) >= (lo) && (u8_t)(c) <= (up))
#define lwip_isdigit(c) lwip_in_range((c), '0', '9')
#define lwip_isxdigit(c) (lwip_isdigit(c) || lwip_in_range((c), 'a', 'f') || lwip_in_range((c), 'A', 'F'))
#define lwip_islower(c) lwip_in_range((c), 'a', 'z')
#define lwip_isspace(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || (c) == '\r' || (c) == '\t' || (c) == '\v')
#define lwip_isupper(c) lwip_in_range((c), 'A', 'Z')
#define lwip_tolower(c) (lwip_isupper(c) ? (c) - 'A' + 'a' : c)
#define lwip_toupper(c) (lwip_islower(c) ? (c) - 'a' + 'A' : c)
#else
#include <ctype.h>
#define lwip_isdigit(c) isdigit((unsigned char)(c))
#define lwip_isxdigit(c) isxdigit((unsigned char)(c))
#define lwip_islower(c) islower((unsigned char)(c))
#define lwip_isspace(c) isspace((unsigned char)(c))
#define lwip_isupper(c) isupper((unsigned char)(c))
#define lwip_tolower(c) tolower((unsigned char)(c))
#define lwip_toupper(c) toupper((unsigned char)(c))
#endif
/** C++ const_cast<target_type>(val) equivalent to remove constness from a value (GCC -Wcast-qual) */
#ifndef LWIP_CONST_CAST
#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val))
#endif
/** Get rid of alignment cast warnings (GCC -Wcast-align) */
#ifndef LWIP_ALIGNMENT_CAST
#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
#endif
/** Get rid of warnings related to pointer-to-numeric and vice-versa casts,
* e.g. "conversion from 'u8_t' to 'void *' of greater size"
*/
#ifndef LWIP_PTR_NUMERIC_CAST
#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
#endif
/** Avoid warnings/errors related to implicitly casting away packed attributes by doing a explicit cast */
#ifndef LWIP_PACKED_CAST
#define LWIP_PACKED_CAST(target_type, val) LWIP_CONST_CAST(target_type, val)
#endif
/** Allocates a memory buffer of specified size that is of sufficient size to align
* its start address using LWIP_MEM_ALIGN.
* You can declare your own version here e.g. to enforce alignment without adding
* trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement
* requirements.\n
* e.g. if you use gcc and need 32 bit alignment:\n
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n
* or more portable:\n
* \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)]
*/
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)]
#endif
/** Calculate memory size for an aligned buffer - returns the next highest
* multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and
* LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4).
*/
#ifndef LWIP_MEM_ALIGN_SIZE
#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U))
#endif
/** Calculate safe memory size for an aligned buffer when using an unaligned
* type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the
* start (e.g. if buffer is u8_t[] and actual data will be u32_t*)
*/
#ifndef LWIP_MEM_ALIGN_BUFFER
#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U))
#endif
/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT
* so that ADDR % MEM_ALIGNMENT == 0
*/
#ifndef LWIP_MEM_ALIGN
#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** Packed structs support.
* Placed BEFORE declaration of a packed struct.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_BEGIN
#define PACK_STRUCT_BEGIN
#endif /* PACK_STRUCT_BEGIN */
/** Packed structs support.
* Placed AFTER declaration of a packed struct.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_END
#define PACK_STRUCT_END
#endif /* PACK_STRUCT_END */
/** Packed structs support.
* Placed between end of declaration of a packed struct and trailing semicolon.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_STRUCT
#if defined(__GNUC__) || defined(__clang__)
#define PACK_STRUCT_STRUCT __attribute__((packed))
#else
#define PACK_STRUCT_STRUCT
#endif
#endif /* PACK_STRUCT_STRUCT */
/** Packed structs support.
* Wraps u32_t and u16_t members.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_FIELD
#define PACK_STRUCT_FIELD(x) x
#endif /* PACK_STRUCT_FIELD */
/** Packed structs support.
* Wraps u8_t members, where some compilers warn that packing is not necessary.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_FLD_8
#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x)
#endif /* PACK_STRUCT_FLD_8 */
/** Packed structs support.
* Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifndef PACK_STRUCT_FLD_S
#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x)
#endif /* PACK_STRUCT_FLD_S */
/** PACK_STRUCT_USE_INCLUDES==1: Packed structs support using \#include files before and after struct to be packed.\n
* The file included BEFORE the struct is "arch/bpstruct.h".\n
* The file included AFTER the struct is "arch/epstruct.h".\n
* This can be used to implement struct packing on MS Visual C compilers, see
* the Win32 port in the lwIP contrib repository for reference.
* For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n
* A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here.
*/
#ifdef __DOXYGEN__
#define PACK_STRUCT_USE_INCLUDES
#endif
/** Eliminates compiler warning about unused arguments (GCC -Wextra -Wunused). */
#ifndef LWIP_UNUSED_ARG
#define LWIP_UNUSED_ARG(x) (void)x
#endif /* LWIP_UNUSED_ARG */
/** LWIP_PROVIDE_ERRNO==1: Let lwIP provide ERRNO values and the 'errno' variable.
* If this is disabled, cc.h must either define 'errno', include <errno.h>,
* define LWIP_ERRNO_STDINCLUDE to get <errno.h> included or
* define LWIP_ERRNO_INCLUDE to <errno.h> or equivalent.
*/
#if defined __DOXYGEN__
#define LWIP_PROVIDE_ERRNO
#endif
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LWIP_HDR_ARCH_H */
@@ -0,0 +1,99 @@
/**
* @file
*
* AutoIP Automatic LinkLocal IP Configuration
*/
/*
*
* Copyright (c) 2007 Dominik Spies <kontakt@dspies.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Dominik Spies <kontakt@dspies.de>
*
* This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
* with RFC 3927.
*
*/
#ifndef LWIP_HDR_AUTOIP_H
#define LWIP_HDR_AUTOIP_H
#include "lwip/opt.h"
#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
#include "lwip/netif.h"
/* #include "lwip/udp.h" */
#include "lwip/etharp.h"
#ifdef __cplusplus
extern "C" {
#endif
/** AutoIP Timing */
#define AUTOIP_TMR_INTERVAL 100
#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL)
/** AutoIP state information per netif */
struct autoip
{
/** the currently selected, probed, announced or used LL IP-Address */
ip4_addr_t llipaddr;
/** current AutoIP state machine state */
u8_t state;
/** sent number of probes or announces, dependent on state */
u8_t sent_num;
/** ticks to wait, tick is AUTOIP_TMR_INTERVAL long */
u16_t ttw;
/** ticks until a conflict can be solved by defending */
u8_t lastconflict;
/** total number of probed/used Link Local IP-Addresses */
u8_t tried_llipaddr;
};
void autoip_set_struct(struct netif *netif, struct autoip *autoip);
/** Remove a struct autoip previously set to the netif using autoip_set_struct() */
#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0)
err_t autoip_start(struct netif *netif);
err_t autoip_stop(struct netif *netif);
void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr);
void autoip_tmr(void);
void autoip_network_changed(struct netif *netif);
u8_t autoip_supplied_address(const struct netif *netif);
/* for lwIP internal use by ip4.c */
u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr);
#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
#ifdef __cplusplus
}
#endif
#endif /* LWIP_IPV4 && LWIP_AUTOIP */
#endif /* LWIP_HDR_AUTOIP_H */
@@ -0,0 +1,161 @@
/**
* @file
* Debug messages infrastructure
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_DEBUG_H
#define LWIP_HDR_DEBUG_H
#include "lwip/arch.h"
#include "lwip/opt.h"
/**
* @defgroup debugging_levels LWIP_DBG_MIN_LEVEL and LWIP_DBG_TYPES_ON values
* @ingroup lwip_opts_debugmsg
* @{
*/
/** @name Debug level (LWIP_DBG_MIN_LEVEL)
* @{
*/
/** Debug level: ALL messages*/
#define LWIP_DBG_LEVEL_ALL 0x00
/** Debug level: Warnings. bad checksums, dropped packets, ... */
#define LWIP_DBG_LEVEL_WARNING 0x01
/** Debug level: Serious. memory allocation failures, ... */
#define LWIP_DBG_LEVEL_SERIOUS 0x02
/** Debug level: Severe */
#define LWIP_DBG_LEVEL_SEVERE 0x03
/**
* @}
*/
#define LWIP_DBG_MASK_LEVEL 0x03
/* compatibility define only */
#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL
/** @name Enable/disable debug messages completely (LWIP_DBG_TYPES_ON)
* @{
*/
/** flag for LWIP_DEBUGF to enable that debug message */
#define LWIP_DBG_ON 0x80U
/** flag for LWIP_DEBUGF to disable that debug message */
#define LWIP_DBG_OFF 0x00U
/**
* @}
*/
/** @name Debug message types (LWIP_DBG_TYPES_ON)
* @{
*/
/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */
#define LWIP_DBG_TRACE 0x40U
/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */
#define LWIP_DBG_STATE 0x20U
/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */
#define LWIP_DBG_FRESH 0x10U
/** flag for LWIP_DEBUGF to halt after printing this debug message */
#define LWIP_DBG_HALT 0x08U
/**
* @}
*/
/**
* @}
*/
/**
* @defgroup lwip_assertions Assertion handling
* @ingroup lwip_opts_debug
* @{
*/
/**
* LWIP_NOASSERT: Disable LWIP_ASSERT checks:
* To disable assertions define LWIP_NOASSERT in arch/cc.h.
*/
#ifdef __DOXYGEN__
#define LWIP_NOASSERT
#undef LWIP_NOASSERT
#endif
/**
* @}
*/
#ifndef LWIP_NOASSERT
#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \
LWIP_PLATFORM_ASSERT(message); }} while(0)
#else /* LWIP_NOASSERT */
#define LWIP_ASSERT(message, assertion)
#endif /* LWIP_NOASSERT */
#ifndef LWIP_ERROR
#ifndef LWIP_NOASSERT
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message)
#elif defined LWIP_DEBUG
#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message))
#else
#define LWIP_PLATFORM_ERROR(message)
#endif
/* if "expression" isn't true, then print "message" and execute "handler" expression */
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
LWIP_PLATFORM_ERROR(message); handler;}} while(0)
#endif /* LWIP_ERROR */
/** Enable debug message printing, but only if debug message type is enabled
* AND is of correct type AND is at least LWIP_DBG_LEVEL.
*/
#ifdef __DOXYGEN__
#define LWIP_DEBUG
#undef LWIP_DEBUG
#endif
#ifdef LWIP_DEBUG
#define LWIP_DEBUGF(debug, message) do { \
if ( \
((debug) & LWIP_DBG_ON) && \
((debug) & LWIP_DBG_TYPES_ON) && \
((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
LWIP_PLATFORM_DIAG(message); \
if ((debug) & LWIP_DBG_HALT) { \
while(1); \
} \
} \
} while(0)
#else /* LWIP_DEBUG */
#define LWIP_DEBUGF(debug, message)
#endif /* LWIP_DEBUG */
#endif /* LWIP_HDR_DEBUG_H */
Loaded 100 of 1812 files, more files were not shown because too many files have changed in this diff. Show more