@mytechtoday/augment-extensions 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/augment-extensions/coding-standards/c/CHANGELOG.md +55 -0
- package/augment-extensions/coding-standards/c/LICENSE +22 -0
- package/augment-extensions/coding-standards/c/README.md +167 -0
- package/augment-extensions/coding-standards/c/config/defaults.json +26 -0
- package/augment-extensions/coding-standards/c/config/examples/embedded.yaml +25 -0
- package/augment-extensions/coding-standards/c/config/examples/systems.json +31 -0
- package/augment-extensions/coding-standards/c/config/schema.json +244 -0
- package/augment-extensions/coding-standards/c/docs/API.md +613 -0
- package/augment-extensions/coding-standards/c/docs/CONFIGURATION.md +259 -0
- package/augment-extensions/coding-standards/c/docs/USER_GUIDE.md +567 -0
- package/augment-extensions/coding-standards/c/examples/drivers/Makefile +33 -0
- package/augment-extensions/coding-standards/c/examples/drivers/README.md +192 -0
- package/augment-extensions/coding-standards/c/examples/drivers/dma-example.c +224 -0
- package/augment-extensions/coding-standards/c/examples/drivers/example.dts +64 -0
- package/augment-extensions/coding-standards/c/examples/drivers/platform-driver.c +174 -0
- package/augment-extensions/coding-standards/c/examples/embedded/README.md +167 -0
- package/augment-extensions/coding-standards/c/examples/embedded/gpio-control.c +172 -0
- package/augment-extensions/coding-standards/c/examples/embedded/timer-isr.c +198 -0
- package/augment-extensions/coding-standards/c/examples/embedded/uart-communication.c +212 -0
- package/augment-extensions/coding-standards/c/examples/kernel/Makefile +82 -0
- package/augment-extensions/coding-standards/c/examples/kernel/README.md +168 -0
- package/augment-extensions/coding-standards/c/examples/kernel/char-device.c +198 -0
- package/augment-extensions/coding-standards/c/examples/kernel/proc-file.c +131 -0
- package/augment-extensions/coding-standards/c/examples/kernel/simple-module.c +111 -0
- package/augment-extensions/coding-standards/c/examples/legacy/Makefile +62 -0
- package/augment-extensions/coding-standards/c/examples/legacy/README.md +255 -0
- package/augment-extensions/coding-standards/c/examples/legacy/c89-to-c11-migration.c +268 -0
- package/augment-extensions/coding-standards/c/examples/legacy/compatibility-layer.c +239 -0
- package/augment-extensions/coding-standards/c/examples/networking/Makefile +35 -0
- package/augment-extensions/coding-standards/c/examples/networking/README.md +207 -0
- package/augment-extensions/coding-standards/c/examples/networking/protocol-parser.c +270 -0
- package/augment-extensions/coding-standards/c/examples/networking/tcp-server.c +197 -0
- package/augment-extensions/coding-standards/c/examples/networking/udp-multicast.c +220 -0
- package/augment-extensions/coding-standards/c/examples/realtime/Makefile +53 -0
- package/augment-extensions/coding-standards/c/examples/realtime/README.md +199 -0
- package/augment-extensions/coding-standards/c/examples/realtime/deadline-monitoring.c +260 -0
- package/augment-extensions/coding-standards/c/examples/realtime/priority-scheduling.c +258 -0
- package/augment-extensions/coding-standards/c/examples/systems/Makefile +34 -0
- package/augment-extensions/coding-standards/c/examples/systems/README.md +123 -0
- package/augment-extensions/coding-standards/c/examples/systems/ipc-pipes.c +181 -0
- package/augment-extensions/coding-standards/c/examples/systems/process-management.c +153 -0
- package/augment-extensions/coding-standards/c/examples/systems/signal-handling.c +162 -0
- package/augment-extensions/coding-standards/c/module.json +149 -0
- package/augment-extensions/coding-standards/c/rules/categories/drivers.md +635 -0
- package/augment-extensions/coding-standards/c/rules/categories/embedded.md +510 -0
- package/augment-extensions/coding-standards/c/rules/categories/kernel.md +653 -0
- package/augment-extensions/coding-standards/c/rules/categories/legacy.md +526 -0
- package/augment-extensions/coding-standards/c/rules/categories/networking.md +735 -0
- package/augment-extensions/coding-standards/c/rules/categories/realtime.md +631 -0
- package/augment-extensions/coding-standards/c/rules/categories/systems.md +586 -0
- package/augment-extensions/coding-standards/c/rules/universal/const-correctness.md +275 -0
- package/augment-extensions/coding-standards/c/rules/universal/documentation.md +251 -0
- package/augment-extensions/coding-standards/c/rules/universal/error-handling.md +250 -0
- package/augment-extensions/coding-standards/c/rules/universal/header-guards.md +254 -0
- package/augment-extensions/coding-standards/c/rules/universal/memory-safety.md +233 -0
- package/augment-extensions/coding-standards/c/rules/universal/naming.md +146 -0
- package/augment-extensions/coding-standards/c/src/conflict-detector.ts +461 -0
- package/augment-extensions/coding-standards/c/src/prompt-generator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-evaluator.ts +307 -0
- package/augment-extensions/coding-standards/c/src/rule-override.ts +427 -0
- package/augment-extensions/coding-standards/c/src/template-engine.ts +217 -0
- package/augment-extensions/coding-standards/c/templates/prompts/drivers.txt +191 -0
- package/augment-extensions/coding-standards/c/templates/prompts/embedded.txt +164 -0
- package/augment-extensions/coding-standards/c/templates/prompts/kernel.txt +175 -0
- package/augment-extensions/coding-standards/c/templates/prompts/legacy.txt +280 -0
- package/augment-extensions/coding-standards/c/templates/prompts/networking.txt +259 -0
- package/augment-extensions/coding-standards/c/templates/prompts/realtime.txt +219 -0
- package/augment-extensions/coding-standards/c/templates/prompts/systems.txt +147 -0
- package/augment-extensions/coding-standards/c/tests/integration/category-specific.test.ts +356 -0
- package/augment-extensions/coding-standards/c/tests/integration/end-to-end-workflow.test.ts +377 -0
- package/augment-extensions/coding-standards/c/tests/performance/benchmarks.test.ts +407 -0
- package/augment-extensions/coding-standards/c/tests/unit/config-manager.test.ts +345 -0
- package/augment-extensions/coding-standards/c/tests/unit/conflict-detector.test.ts +294 -0
- package/augment-extensions/coding-standards/c/tests/unit/prompt-generator.test.ts +174 -0
- package/augment-extensions/coding-standards/c/tests/unit/registry.test.ts +313 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-evaluator.test.ts +318 -0
- package/augment-extensions/coding-standards/c/tests/unit/rule-override.test.ts +326 -0
- package/augment-extensions/coding-standards/c/tests/unit/template-engine.test.ts +314 -0
- package/augment-extensions/coding-standards/go/CHARACTER-COUNT-REPORT.md +135 -0
- package/augment-extensions/coding-standards/go/PHASE1-COMPLETION.md +146 -0
- package/augment-extensions/coding-standards/go/PHASE4-COMPLETION.md +184 -0
- package/augment-extensions/coding-standards/go/README.md +200 -0
- package/augment-extensions/coding-standards/go/VALIDATION-CHECKLIST.md +154 -0
- package/augment-extensions/coding-standards/go/config/examples/example-cli.json +15 -0
- package/augment-extensions/coding-standards/go/config/examples/example-microservices.json +21 -0
- package/augment-extensions/coding-standards/go/config/examples/example-multi-category.yaml +24 -0
- package/augment-extensions/coding-standards/go/config/examples/example-web.json +15 -0
- package/augment-extensions/coding-standards/go/config/schema.json +110 -0
- package/augment-extensions/coding-standards/go/docs/CATEGORIES.md +221 -0
- package/augment-extensions/coding-standards/go/docs/CONFIGURATION.md +198 -0
- package/augment-extensions/coding-standards/go/docs/TROUBLESHOOTING.md +285 -0
- package/augment-extensions/coding-standards/go/examples/cli/cobra-app.go +287 -0
- package/augment-extensions/coding-standards/go/examples/cloud-native-app.go +217 -0
- package/augment-extensions/coding-standards/go/examples/devops-tool.go +250 -0
- package/augment-extensions/coding-standards/go/examples/distributed-system.go +247 -0
- package/augment-extensions/coding-standards/go/examples/microservices/grpc-service.go +253 -0
- package/augment-extensions/coding-standards/go/examples/rest-api.go +270 -0
- package/augment-extensions/coding-standards/go/examples/web/http-server.go +224 -0
- package/augment-extensions/coding-standards/go/module.json +139 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/api-versioning.md +149 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rate-limiting.md +209 -0
- package/augment-extensions/coding-standards/go/rules/categories/api-development/rest-api-design.md +183 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/cloud-config.md +193 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/health-checks.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/cloud-native/kubernetes.md +180 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/automation.md +179 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/ci-cd-integration.md +147 -0
- package/augment-extensions/coding-standards/go/rules/categories/devops-tooling/infrastructure-as-code.md +231 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/caching.md +150 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/consensus.md +187 -0
- package/augment-extensions/coding-standards/go/rules/categories/distributed-systems/event-sourcing.md +246 -0
- package/augment-extensions/coding-standards/go/rules/cli/command-parsing.md +264 -0
- package/augment-extensions/coding-standards/go/rules/cli/configuration.md +268 -0
- package/augment-extensions/coding-standards/go/rules/cli/cross-platform.md +324 -0
- package/augment-extensions/coding-standards/go/rules/microservices/distributed-tracing.md +253 -0
- package/augment-extensions/coding-standards/go/rules/microservices/grpc.md +257 -0
- package/augment-extensions/coding-standards/go/rules/microservices/metrics.md +278 -0
- package/augment-extensions/coding-standards/go/rules/microservices/service-discovery.md +249 -0
- package/augment-extensions/coding-standards/go/rules/universal/code-organization.md +221 -0
- package/augment-extensions/coding-standards/go/rules/universal/documentation.md +269 -0
- package/augment-extensions/coding-standards/go/rules/universal/performance.md +323 -0
- package/augment-extensions/coding-standards/go/rules/universal/testing.md +162 -0
- package/augment-extensions/coding-standards/go/rules/web/graceful-shutdown.md +249 -0
- package/augment-extensions/coding-standards/go/rules/web/http-handlers.md +164 -0
- package/augment-extensions/coding-standards/go/rules/web/middleware.md +234 -0
- package/augment-extensions/coding-standards/go/rules/web/routing.md +251 -0
- package/augment-extensions/coding-standards/go/templates/prompts/api.md +160 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cli.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/cloud-native.md +121 -0
- package/augment-extensions/coding-standards/go/templates/prompts/devops.md +146 -0
- package/augment-extensions/coding-standards/go/templates/prompts/distributed.md +133 -0
- package/augment-extensions/coding-standards/go/templates/prompts/microservices.md +225 -0
- package/augment-extensions/coding-standards/go/templates/prompts/web.md +181 -0
- package/augment-extensions/coding-standards/go/tests/integration/module-integration.test.ts +164 -0
- package/augment-extensions/coding-standards/go/tests/unit/category-selection.test.ts +147 -0
- package/augment-extensions/coding-standards/go/tests/unit/module-structure.test.ts +154 -0
- package/augment-extensions/coding-standards/go/tests/validate-character-count.ps1 +13 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.ps1 +148 -0
- package/augment-extensions/coding-standards/go/tests/validate-examples.sh +135 -0
- package/cli/dist/analysis/ast-parser.d.ts +47 -0
- package/cli/dist/analysis/ast-parser.d.ts.map +1 -0
- package/cli/dist/analysis/ast-parser.js +161 -0
- package/cli/dist/analysis/ast-parser.js.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts +27 -0
- package/cli/dist/analysis/complexity-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/complexity-analyzer.js +189 -0
- package/cli/dist/analysis/complexity-analyzer.js.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts +23 -0
- package/cli/dist/analysis/dependency-analyzer.d.ts.map +1 -0
- package/cli/dist/analysis/dependency-analyzer.js +237 -0
- package/cli/dist/analysis/dependency-analyzer.js.map +1 -0
- package/cli/dist/analysis/index.d.ts +9 -0
- package/cli/dist/analysis/index.d.ts.map +1 -0
- package/cli/dist/analysis/index.js +25 -0
- package/cli/dist/analysis/index.js.map +1 -0
- package/cli/dist/analysis/security-scanner.d.ts +11 -0
- package/cli/dist/analysis/security-scanner.d.ts.map +1 -0
- package/cli/dist/analysis/security-scanner.js +294 -0
- package/cli/dist/analysis/security-scanner.js.map +1 -0
- package/cli/dist/analysis/types.d.ts +151 -0
- package/cli/dist/analysis/types.d.ts.map +1 -0
- package/cli/dist/analysis/types.js +6 -0
- package/cli/dist/analysis/types.js.map +1 -0
- package/cli/dist/cli.js +24 -0
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/code-analysis.d.ts +11 -0
- package/cli/dist/commands/code-analysis.d.ts.map +1 -0
- package/cli/dist/commands/code-analysis.js +412 -0
- package/cli/dist/commands/code-analysis.js.map +1 -0
- package/modules.md +99 -3
- package/package.json +14 -2
- package/cli/dist/commands/agent.d.ts +0 -37
- package/cli/dist/commands/agent.d.ts.map +0 -1
- package/cli/dist/commands/agent.js +0 -222
- package/cli/dist/commands/agent.js.map +0 -1
- package/cli/dist/commands/beads.d.ts +0 -64
- package/cli/dist/commands/beads.d.ts.map +0 -1
- package/cli/dist/commands/beads.js +0 -377
- package/cli/dist/commands/beads.js.map +0 -1
- package/cli/dist/commands/change.d.ts +0 -54
- package/cli/dist/commands/change.d.ts.map +0 -1
- package/cli/dist/commands/change.js +0 -243
- package/cli/dist/commands/change.js.map +0 -1
- package/cli/dist/commands/clean.d.ts +0 -15
- package/cli/dist/commands/clean.d.ts.map +0 -1
- package/cli/dist/commands/clean.js +0 -63
- package/cli/dist/commands/clean.js.map +0 -1
- package/cli/dist/commands/clone.d.ts +0 -15
- package/cli/dist/commands/clone.d.ts.map +0 -1
- package/cli/dist/commands/clone.js +0 -49
- package/cli/dist/commands/clone.js.map +0 -1
- package/cli/dist/commands/config.d.ts +0 -33
- package/cli/dist/commands/config.d.ts.map +0 -1
- package/cli/dist/commands/config.js +0 -166
- package/cli/dist/commands/config.js.map +0 -1
- package/cli/dist/commands/context.d.ts +0 -38
- package/cli/dist/commands/context.d.ts.map +0 -1
- package/cli/dist/commands/context.js +0 -205
- package/cli/dist/commands/context.js.map +0 -1
- package/cli/dist/commands/create.d.ts +0 -18
- package/cli/dist/commands/create.d.ts.map +0 -1
- package/cli/dist/commands/create.js +0 -178
- package/cli/dist/commands/create.js.map +0 -1
- package/cli/dist/commands/diff.d.ts +0 -19
- package/cli/dist/commands/diff.d.ts.map +0 -1
- package/cli/dist/commands/diff.js +0 -104
- package/cli/dist/commands/diff.js.map +0 -1
- package/cli/dist/commands/doctor.d.ts +0 -14
- package/cli/dist/commands/doctor.d.ts.map +0 -1
- package/cli/dist/commands/doctor.js +0 -62
- package/cli/dist/commands/doctor.js.map +0 -1
- package/cli/dist/commands/export.d.ts +0 -28
- package/cli/dist/commands/export.d.ts.map +0 -1
- package/cli/dist/commands/export.js +0 -135
- package/cli/dist/commands/export.js.map +0 -1
- package/cli/dist/commands/import.d.ts +0 -23
- package/cli/dist/commands/import.d.ts.map +0 -1
- package/cli/dist/commands/import.js +0 -118
- package/cli/dist/commands/import.js.map +0 -1
- package/cli/dist/commands/prompt.d.ts +0 -45
- package/cli/dist/commands/prompt.d.ts.map +0 -1
- package/cli/dist/commands/prompt.js +0 -223
- package/cli/dist/commands/prompt.js.map +0 -1
- package/cli/dist/commands/spec.d.ts +0 -57
- package/cli/dist/commands/spec.d.ts.map +0 -1
- package/cli/dist/commands/spec.js +0 -279
- package/cli/dist/commands/spec.js.map +0 -1
- package/cli/dist/commands/stats.d.ts +0 -18
- package/cli/dist/commands/stats.d.ts.map +0 -1
- package/cli/dist/commands/stats.js +0 -85
- package/cli/dist/commands/stats.js.map +0 -1
- package/cli/dist/commands/task.d.ts +0 -65
- package/cli/dist/commands/task.d.ts.map +0 -1
- package/cli/dist/commands/task.js +0 -282
- package/cli/dist/commands/task.js.map +0 -1
- package/cli/dist/commands/template.d.ts +0 -17
- package/cli/dist/commands/template.d.ts.map +0 -1
- package/cli/dist/commands/template.js +0 -55
- package/cli/dist/commands/template.js.map +0 -1
- package/cli/dist/utils/agent-config.d.ts +0 -129
- package/cli/dist/utils/agent-config.d.ts.map +0 -1
- package/cli/dist/utils/agent-config.js +0 -297
- package/cli/dist/utils/agent-config.js.map +0 -1
- package/cli/dist/utils/beads-graph.d.ts +0 -17
- package/cli/dist/utils/beads-graph.d.ts.map +0 -1
- package/cli/dist/utils/beads-graph.js +0 -150
- package/cli/dist/utils/beads-graph.js.map +0 -1
- package/cli/dist/utils/beads-integration.d.ts +0 -112
- package/cli/dist/utils/beads-integration.d.ts.map +0 -1
- package/cli/dist/utils/beads-integration.js +0 -312
- package/cli/dist/utils/beads-integration.js.map +0 -1
- package/cli/dist/utils/beads-reporter.d.ts +0 -17
- package/cli/dist/utils/beads-reporter.d.ts.map +0 -1
- package/cli/dist/utils/beads-reporter.js +0 -160
- package/cli/dist/utils/beads-reporter.js.map +0 -1
- package/cli/dist/utils/cache-manager.d.ts +0 -55
- package/cli/dist/utils/cache-manager.d.ts.map +0 -1
- package/cli/dist/utils/cache-manager.js +0 -150
- package/cli/dist/utils/cache-manager.js.map +0 -1
- package/cli/dist/utils/change-manager.d.ts +0 -70
- package/cli/dist/utils/change-manager.d.ts.map +0 -1
- package/cli/dist/utils/change-manager.js +0 -412
- package/cli/dist/utils/change-manager.js.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.d.ts +0 -66
- package/cli/dist/utils/config-manager-enhanced.d.ts.map +0 -1
- package/cli/dist/utils/config-manager-enhanced.js +0 -77
- package/cli/dist/utils/config-manager-enhanced.js.map +0 -1
- package/cli/dist/utils/context-manager.d.ts +0 -96
- package/cli/dist/utils/context-manager.d.ts.map +0 -1
- package/cli/dist/utils/context-manager.js +0 -258
- package/cli/dist/utils/context-manager.js.map +0 -1
- package/cli/dist/utils/diff-engine.d.ts +0 -78
- package/cli/dist/utils/diff-engine.d.ts.map +0 -1
- package/cli/dist/utils/diff-engine.js +0 -233
- package/cli/dist/utils/diff-engine.js.map +0 -1
- package/cli/dist/utils/export-system.d.ts +0 -101
- package/cli/dist/utils/export-system.d.ts.map +0 -1
- package/cli/dist/utils/export-system.js +0 -289
- package/cli/dist/utils/export-system.js.map +0 -1
- package/cli/dist/utils/health-checker.d.ts +0 -66
- package/cli/dist/utils/health-checker.d.ts.map +0 -1
- package/cli/dist/utils/health-checker.js +0 -285
- package/cli/dist/utils/health-checker.js.map +0 -1
- package/cli/dist/utils/import-system.d.ts +0 -74
- package/cli/dist/utils/import-system.d.ts.map +0 -1
- package/cli/dist/utils/import-system.js +0 -317
- package/cli/dist/utils/import-system.js.map +0 -1
- package/cli/dist/utils/module-cloner.d.ts +0 -40
- package/cli/dist/utils/module-cloner.d.ts.map +0 -1
- package/cli/dist/utils/module-cloner.js +0 -136
- package/cli/dist/utils/module-cloner.js.map +0 -1
- package/cli/dist/utils/prompt-manager.d.ts +0 -90
- package/cli/dist/utils/prompt-manager.d.ts.map +0 -1
- package/cli/dist/utils/prompt-manager.js +0 -302
- package/cli/dist/utils/prompt-manager.js.map +0 -1
- package/cli/dist/utils/spec-manager.d.ts +0 -65
- package/cli/dist/utils/spec-manager.d.ts.map +0 -1
- package/cli/dist/utils/spec-manager.js +0 -329
- package/cli/dist/utils/spec-manager.js.map +0 -1
- package/cli/dist/utils/stats-collector.d.ts +0 -74
- package/cli/dist/utils/stats-collector.d.ts.map +0 -1
- package/cli/dist/utils/stats-collector.js +0 -164
- package/cli/dist/utils/stats-collector.js.map +0 -1
- package/cli/dist/utils/template-engine.d.ts +0 -47
- package/cli/dist/utils/template-engine.d.ts.map +0 -1
- package/cli/dist/utils/template-engine.js +0 -204
- package/cli/dist/utils/template-engine.js.map +0 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Networking Examples
|
|
2
|
+
|
|
3
|
+
This directory contains network programming examples demonstrating socket programming and protocol handling.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### 1. tcp-server.c
|
|
8
|
+
TCP server with connection handling:
|
|
9
|
+
- Socket creation and binding
|
|
10
|
+
- Connection acceptance
|
|
11
|
+
- Echo server implementation
|
|
12
|
+
- Error handling
|
|
13
|
+
- Resource cleanup
|
|
14
|
+
|
|
15
|
+
**Key Concepts:**
|
|
16
|
+
- Use `SO_REUSEADDR` for quick restart
|
|
17
|
+
- Check all socket operation return values
|
|
18
|
+
- Close sockets properly
|
|
19
|
+
- Handle partial reads/writes
|
|
20
|
+
|
|
21
|
+
### 2. udp-multicast.c
|
|
22
|
+
UDP multicast sender and receiver:
|
|
23
|
+
- Multicast group management
|
|
24
|
+
- Sending multicast packets
|
|
25
|
+
- Receiving multicast packets
|
|
26
|
+
- TTL configuration
|
|
27
|
+
- Multiple receivers
|
|
28
|
+
|
|
29
|
+
**Key Concepts:**
|
|
30
|
+
- Join multicast group with `IP_ADD_MEMBERSHIP`
|
|
31
|
+
- Set multicast TTL appropriately
|
|
32
|
+
- Use `SO_REUSEADDR` for multiple receivers
|
|
33
|
+
- Multicast addresses: 224.0.0.0 to 239.255.255.255
|
|
34
|
+
|
|
35
|
+
### 3. protocol-parser.c
|
|
36
|
+
Binary protocol parser:
|
|
37
|
+
- State machine parsing
|
|
38
|
+
- Endianness handling
|
|
39
|
+
- Checksum validation
|
|
40
|
+
- Error detection
|
|
41
|
+
- Input validation
|
|
42
|
+
|
|
43
|
+
**Key Concepts:**
|
|
44
|
+
- Parse byte-by-byte with state machine
|
|
45
|
+
- Validate all inputs
|
|
46
|
+
- Handle network byte order (big-endian)
|
|
47
|
+
- Implement error recovery
|
|
48
|
+
|
|
49
|
+
## Building
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Build all examples
|
|
53
|
+
make
|
|
54
|
+
|
|
55
|
+
# Build specific example
|
|
56
|
+
make tcp-server
|
|
57
|
+
|
|
58
|
+
# Clean
|
|
59
|
+
make clean
|
|
60
|
+
|
|
61
|
+
# Run tests
|
|
62
|
+
make test
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Running Examples
|
|
66
|
+
|
|
67
|
+
### TCP Server
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Terminal 1: Start server
|
|
71
|
+
./tcp-server 8080
|
|
72
|
+
|
|
73
|
+
# Terminal 2: Connect with telnet
|
|
74
|
+
telnet localhost 8080
|
|
75
|
+
|
|
76
|
+
# Or use netcat
|
|
77
|
+
nc localhost 8080
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### UDP Multicast
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Terminal 1: Start receiver
|
|
84
|
+
./udp-multicast recv 239.0.0.1 5000
|
|
85
|
+
|
|
86
|
+
# Terminal 2: Start sender
|
|
87
|
+
./udp-multicast send 239.0.0.1 5000
|
|
88
|
+
|
|
89
|
+
# You can run multiple receivers
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Protocol Parser
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Run parser test
|
|
96
|
+
./protocol-parser
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Network Programming Best Practices
|
|
100
|
+
|
|
101
|
+
1. **Error Handling**
|
|
102
|
+
- Check all socket operations
|
|
103
|
+
- Handle `EINTR` for interrupted system calls
|
|
104
|
+
- Handle `EAGAIN`/`EWOULDBLOCK` for non-blocking I/O
|
|
105
|
+
- Close sockets on error
|
|
106
|
+
|
|
107
|
+
2. **Resource Management**
|
|
108
|
+
- Always close sockets
|
|
109
|
+
- Use `SO_REUSEADDR` for servers
|
|
110
|
+
- Set appropriate timeouts
|
|
111
|
+
- Limit buffer sizes
|
|
112
|
+
|
|
113
|
+
3. **Protocol Design**
|
|
114
|
+
- Use network byte order (big-endian)
|
|
115
|
+
- Include length fields
|
|
116
|
+
- Add checksums for integrity
|
|
117
|
+
- Version your protocol
|
|
118
|
+
|
|
119
|
+
4. **Security**
|
|
120
|
+
- Validate all inputs
|
|
121
|
+
- Limit buffer sizes
|
|
122
|
+
- Use timeouts
|
|
123
|
+
- Handle malformed data
|
|
124
|
+
|
|
125
|
+
## Common Pitfalls
|
|
126
|
+
|
|
127
|
+
1. **Forgetting Network Byte Order**
|
|
128
|
+
```c
|
|
129
|
+
// WRONG
|
|
130
|
+
uint16_t port = 8080;
|
|
131
|
+
addr.sin_port = port;
|
|
132
|
+
|
|
133
|
+
// CORRECT
|
|
134
|
+
addr.sin_port = htons(8080);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
2. **Not Handling Partial Reads/Writes**
|
|
138
|
+
```c
|
|
139
|
+
// WRONG - Assumes all data sent
|
|
140
|
+
send(sockfd, buffer, size, 0);
|
|
141
|
+
|
|
142
|
+
// CORRECT - Handle partial sends
|
|
143
|
+
size_t sent = 0;
|
|
144
|
+
while (sent < size) {
|
|
145
|
+
ssize_t n = send(sockfd, buffer + sent, size - sent, 0);
|
|
146
|
+
if (n < 0) { /* error */ }
|
|
147
|
+
sent += n;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
3. **Not Closing Sockets**
|
|
152
|
+
```c
|
|
153
|
+
// WRONG - Socket leak
|
|
154
|
+
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
155
|
+
if (bind(sockfd, ...) < 0) {
|
|
156
|
+
return -1; // Leaked socket!
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// CORRECT
|
|
160
|
+
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
161
|
+
if (bind(sockfd, ...) < 0) {
|
|
162
|
+
close(sockfd);
|
|
163
|
+
return -1;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
4. **Buffer Overflows**
|
|
168
|
+
```c
|
|
169
|
+
// WRONG - No bounds checking
|
|
170
|
+
char buffer[100];
|
|
171
|
+
recv(sockfd, buffer, 1000, 0); // Overflow!
|
|
172
|
+
|
|
173
|
+
// CORRECT
|
|
174
|
+
char buffer[100];
|
|
175
|
+
ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
|
|
176
|
+
if (n > 0) {
|
|
177
|
+
buffer[n] = '\0';
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Protocol Format
|
|
182
|
+
|
|
183
|
+
The example protocol uses this format:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
+--------+--------+--------+--------+--------+--------+
|
|
187
|
+
| MAGIC | MAGIC | TYPE | LENGTH | LENGTH | CHKSUM |
|
|
188
|
+
| (MSB) | (LSB) | | (MSB) | (LSB) | |
|
|
189
|
+
+--------+--------+--------+--------+--------+--------+
|
|
190
|
+
| PAYLOAD (variable length) |
|
|
191
|
+
+----------------------------------------------------+
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
- **MAGIC**: 0xABCD (protocol identifier)
|
|
195
|
+
- **TYPE**: Message type (1 byte)
|
|
196
|
+
- **LENGTH**: Payload length in bytes (2 bytes, big-endian)
|
|
197
|
+
- **CHECKSUM**: XOR checksum of payload
|
|
198
|
+
- **PAYLOAD**: Message data
|
|
199
|
+
|
|
200
|
+
## References
|
|
201
|
+
|
|
202
|
+
- POSIX Socket API: https://pubs.opengroup.org/onlinepubs/9699919799/
|
|
203
|
+
- TCP/IP Illustrated by W. Richard Stevens
|
|
204
|
+
- Unix Network Programming by W. Richard Stevens
|
|
205
|
+
- RFC 1112: Host Extensions for IP Multicasting
|
|
206
|
+
- Beej's Guide to Network Programming
|
|
207
|
+
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file protocol-parser.c
|
|
3
|
+
* @brief Example binary protocol parser with error handling
|
|
4
|
+
*
|
|
5
|
+
* This example demonstrates:
|
|
6
|
+
* - Binary protocol parsing
|
|
7
|
+
* - Endianness handling
|
|
8
|
+
* - Input validation
|
|
9
|
+
* - State machine for parsing
|
|
10
|
+
* - Error detection and recovery
|
|
11
|
+
*
|
|
12
|
+
* Protocol Format:
|
|
13
|
+
* Header: [MAGIC(2)] [TYPE(1)] [LENGTH(2)] [CHECKSUM(1)]
|
|
14
|
+
* Payload: [DATA(LENGTH)]
|
|
15
|
+
*
|
|
16
|
+
* Compile: gcc -Wall -Wextra -std=c11 -o protocol-parser protocol-parser.c
|
|
17
|
+
* Run: ./protocol-parser
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
#include <stdio.h>
|
|
21
|
+
#include <stdlib.h>
|
|
22
|
+
#include <string.h>
|
|
23
|
+
#include <stdint.h>
|
|
24
|
+
#include <stdbool.h>
|
|
25
|
+
#include <arpa/inet.h> /* For ntohs/htons */
|
|
26
|
+
|
|
27
|
+
#define PROTOCOL_MAGIC 0xABCD
|
|
28
|
+
#define MAX_PAYLOAD_SIZE 1024
|
|
29
|
+
#define HEADER_SIZE 6
|
|
30
|
+
|
|
31
|
+
/* Message types */
|
|
32
|
+
typedef enum {
|
|
33
|
+
MSG_TYPE_DATA = 0x01,
|
|
34
|
+
MSG_TYPE_ACK = 0x02,
|
|
35
|
+
MSG_TYPE_NACK = 0x03,
|
|
36
|
+
MSG_TYPE_PING = 0x04,
|
|
37
|
+
MSG_TYPE_PONG = 0x05
|
|
38
|
+
} message_type_t;
|
|
39
|
+
|
|
40
|
+
/* Parser states */
|
|
41
|
+
typedef enum {
|
|
42
|
+
STATE_WAIT_MAGIC,
|
|
43
|
+
STATE_WAIT_TYPE,
|
|
44
|
+
STATE_WAIT_LENGTH,
|
|
45
|
+
STATE_WAIT_CHECKSUM,
|
|
46
|
+
STATE_WAIT_PAYLOAD,
|
|
47
|
+
STATE_COMPLETE,
|
|
48
|
+
STATE_ERROR
|
|
49
|
+
} parser_state_t;
|
|
50
|
+
|
|
51
|
+
/* Protocol message structure */
|
|
52
|
+
typedef struct {
|
|
53
|
+
uint16_t magic;
|
|
54
|
+
uint8_t type;
|
|
55
|
+
uint16_t length;
|
|
56
|
+
uint8_t checksum;
|
|
57
|
+
uint8_t payload[MAX_PAYLOAD_SIZE];
|
|
58
|
+
} protocol_message_t;
|
|
59
|
+
|
|
60
|
+
/* Parser context */
|
|
61
|
+
typedef struct {
|
|
62
|
+
parser_state_t state;
|
|
63
|
+
protocol_message_t message;
|
|
64
|
+
size_t bytes_received;
|
|
65
|
+
size_t payload_received;
|
|
66
|
+
} parser_context_t;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @brief Calculate simple checksum
|
|
70
|
+
*/
|
|
71
|
+
static uint8_t calculate_checksum(const uint8_t *data, size_t length) {
|
|
72
|
+
uint8_t checksum = 0;
|
|
73
|
+
for (size_t i = 0; i < length; i++) {
|
|
74
|
+
checksum ^= data[i];
|
|
75
|
+
}
|
|
76
|
+
return checksum;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @brief Initialize parser context
|
|
81
|
+
*/
|
|
82
|
+
static void parser_init(parser_context_t *ctx) {
|
|
83
|
+
memset(ctx, 0, sizeof(*ctx));
|
|
84
|
+
ctx->state = STATE_WAIT_MAGIC;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @brief Parse incoming byte
|
|
89
|
+
* @return true if message complete, false otherwise
|
|
90
|
+
*/
|
|
91
|
+
static bool parser_process_byte(parser_context_t *ctx, uint8_t byte) {
|
|
92
|
+
switch (ctx->state) {
|
|
93
|
+
case STATE_WAIT_MAGIC:
|
|
94
|
+
if (ctx->bytes_received == 0) {
|
|
95
|
+
/* First byte of magic */
|
|
96
|
+
ctx->message.magic = byte << 8;
|
|
97
|
+
ctx->bytes_received = 1;
|
|
98
|
+
} else {
|
|
99
|
+
/* Second byte of magic */
|
|
100
|
+
ctx->message.magic |= byte;
|
|
101
|
+
if (ctx->message.magic == PROTOCOL_MAGIC) {
|
|
102
|
+
ctx->state = STATE_WAIT_TYPE;
|
|
103
|
+
ctx->bytes_received = 0;
|
|
104
|
+
} else {
|
|
105
|
+
/* Invalid magic, reset */
|
|
106
|
+
printf("Error: Invalid magic 0x%04X\n", ctx->message.magic);
|
|
107
|
+
parser_init(ctx);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
|
|
112
|
+
case STATE_WAIT_TYPE:
|
|
113
|
+
ctx->message.type = byte;
|
|
114
|
+
ctx->state = STATE_WAIT_LENGTH;
|
|
115
|
+
ctx->bytes_received = 0;
|
|
116
|
+
break;
|
|
117
|
+
|
|
118
|
+
case STATE_WAIT_LENGTH:
|
|
119
|
+
if (ctx->bytes_received == 0) {
|
|
120
|
+
/* First byte of length (MSB) */
|
|
121
|
+
ctx->message.length = byte << 8;
|
|
122
|
+
ctx->bytes_received = 1;
|
|
123
|
+
} else {
|
|
124
|
+
/* Second byte of length (LSB) */
|
|
125
|
+
ctx->message.length |= byte;
|
|
126
|
+
if (ctx->message.length > MAX_PAYLOAD_SIZE) {
|
|
127
|
+
printf("Error: Payload too large (%u bytes)\n", ctx->message.length);
|
|
128
|
+
ctx->state = STATE_ERROR;
|
|
129
|
+
} else {
|
|
130
|
+
ctx->state = STATE_WAIT_CHECKSUM;
|
|
131
|
+
ctx->bytes_received = 0;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
|
|
136
|
+
case STATE_WAIT_CHECKSUM:
|
|
137
|
+
ctx->message.checksum = byte;
|
|
138
|
+
if (ctx->message.length > 0) {
|
|
139
|
+
ctx->state = STATE_WAIT_PAYLOAD;
|
|
140
|
+
ctx->payload_received = 0;
|
|
141
|
+
} else {
|
|
142
|
+
/* No payload, verify checksum */
|
|
143
|
+
uint8_t expected = calculate_checksum(NULL, 0);
|
|
144
|
+
if (ctx->message.checksum == expected) {
|
|
145
|
+
ctx->state = STATE_COMPLETE;
|
|
146
|
+
return true;
|
|
147
|
+
} else {
|
|
148
|
+
printf("Error: Checksum mismatch\n");
|
|
149
|
+
ctx->state = STATE_ERROR;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
|
|
154
|
+
case STATE_WAIT_PAYLOAD:
|
|
155
|
+
ctx->message.payload[ctx->payload_received++] = byte;
|
|
156
|
+
if (ctx->payload_received >= ctx->message.length) {
|
|
157
|
+
/* Verify checksum */
|
|
158
|
+
uint8_t expected = calculate_checksum(ctx->message.payload,
|
|
159
|
+
ctx->message.length);
|
|
160
|
+
if (ctx->message.checksum == expected) {
|
|
161
|
+
ctx->state = STATE_COMPLETE;
|
|
162
|
+
return true;
|
|
163
|
+
} else {
|
|
164
|
+
printf("Error: Checksum mismatch (expected 0x%02X, got 0x%02X)\n",
|
|
165
|
+
expected, ctx->message.checksum);
|
|
166
|
+
ctx->state = STATE_ERROR;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
|
|
171
|
+
case STATE_COMPLETE:
|
|
172
|
+
case STATE_ERROR:
|
|
173
|
+
/* Reset parser */
|
|
174
|
+
parser_init(ctx);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @brief Create protocol message
|
|
183
|
+
*/
|
|
184
|
+
static size_t create_message(uint8_t *buffer, size_t buffer_size,
|
|
185
|
+
message_type_t type, const uint8_t *payload,
|
|
186
|
+
uint16_t payload_len) {
|
|
187
|
+
if (buffer_size < HEADER_SIZE + payload_len) {
|
|
188
|
+
return 0; /* Buffer too small */
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
size_t offset = 0;
|
|
192
|
+
|
|
193
|
+
/* Magic (big-endian) */
|
|
194
|
+
uint16_t magic = htons(PROTOCOL_MAGIC);
|
|
195
|
+
memcpy(buffer + offset, &magic, 2);
|
|
196
|
+
offset += 2;
|
|
197
|
+
|
|
198
|
+
/* Type */
|
|
199
|
+
buffer[offset++] = type;
|
|
200
|
+
|
|
201
|
+
/* Length (big-endian) */
|
|
202
|
+
uint16_t length = htons(payload_len);
|
|
203
|
+
memcpy(buffer + offset, &length, 2);
|
|
204
|
+
offset += 2;
|
|
205
|
+
|
|
206
|
+
/* Checksum */
|
|
207
|
+
uint8_t checksum = calculate_checksum(payload, payload_len);
|
|
208
|
+
buffer[offset++] = checksum;
|
|
209
|
+
|
|
210
|
+
/* Payload */
|
|
211
|
+
if (payload_len > 0) {
|
|
212
|
+
memcpy(buffer + offset, payload, payload_len);
|
|
213
|
+
offset += payload_len;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return offset;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @brief Print parsed message
|
|
221
|
+
*/
|
|
222
|
+
static void print_message(const protocol_message_t *msg) {
|
|
223
|
+
printf("\n=== Parsed Message ===\n");
|
|
224
|
+
printf("Magic: 0x%04X\n", msg->magic);
|
|
225
|
+
printf("Type: 0x%02X\n", msg->type);
|
|
226
|
+
printf("Length: %u bytes\n", msg->length);
|
|
227
|
+
printf("Checksum: 0x%02X\n", msg->checksum);
|
|
228
|
+
if (msg->length > 0) {
|
|
229
|
+
printf("Payload: ");
|
|
230
|
+
for (uint16_t i = 0; i < msg->length && i < 32; i++) {
|
|
231
|
+
printf("%02X ", msg->payload[i]);
|
|
232
|
+
}
|
|
233
|
+
if (msg->length > 32) {
|
|
234
|
+
printf("...");
|
|
235
|
+
}
|
|
236
|
+
printf("\n");
|
|
237
|
+
}
|
|
238
|
+
printf("=====================\n\n");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @brief Test protocol parser
|
|
243
|
+
*/
|
|
244
|
+
int main(void) {
|
|
245
|
+
uint8_t buffer[256];
|
|
246
|
+
parser_context_t parser;
|
|
247
|
+
|
|
248
|
+
printf("Protocol Parser Example\n\n");
|
|
249
|
+
|
|
250
|
+
/* Create test message */
|
|
251
|
+
const char *test_data = "Hello, Protocol!";
|
|
252
|
+
size_t msg_len = create_message(buffer, sizeof(buffer),
|
|
253
|
+
MSG_TYPE_DATA,
|
|
254
|
+
(const uint8_t *)test_data,
|
|
255
|
+
strlen(test_data));
|
|
256
|
+
|
|
257
|
+
printf("Created message of %zu bytes\n", msg_len);
|
|
258
|
+
|
|
259
|
+
/* Parse message byte by byte */
|
|
260
|
+
parser_init(&parser);
|
|
261
|
+
for (size_t i = 0; i < msg_len; i++) {
|
|
262
|
+
if (parser_process_byte(&parser, buffer[i])) {
|
|
263
|
+
printf("Message parsed successfully!\n");
|
|
264
|
+
print_message(&parser.message);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return EXIT_SUCCESS;
|
|
269
|
+
}
|
|
270
|
+
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file tcp-server.c
|
|
3
|
+
* @brief Example TCP server with proper error handling
|
|
4
|
+
*
|
|
5
|
+
* This example demonstrates:
|
|
6
|
+
* - TCP socket creation and binding
|
|
7
|
+
* - Connection handling
|
|
8
|
+
* - Non-blocking I/O
|
|
9
|
+
* - Error handling
|
|
10
|
+
* - Resource cleanup
|
|
11
|
+
*
|
|
12
|
+
* Compile: gcc -Wall -Wextra -std=c11 -o tcp-server tcp-server.c
|
|
13
|
+
* Run: ./tcp-server 8080
|
|
14
|
+
* Test: telnet localhost 8080
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include <stdio.h>
|
|
18
|
+
#include <stdlib.h>
|
|
19
|
+
#include <string.h>
|
|
20
|
+
#include <unistd.h>
|
|
21
|
+
#include <errno.h>
|
|
22
|
+
#include <sys/types.h>
|
|
23
|
+
#include <sys/socket.h>
|
|
24
|
+
#include <netinet/in.h>
|
|
25
|
+
#include <arpa/inet.h>
|
|
26
|
+
#include <fcntl.h>
|
|
27
|
+
|
|
28
|
+
#define BUFFER_SIZE 1024
|
|
29
|
+
#define MAX_PENDING 5
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @brief Set socket to non-blocking mode
|
|
33
|
+
*/
|
|
34
|
+
static int set_nonblocking(int sockfd) {
|
|
35
|
+
int flags = fcntl(sockfd, F_GETFL, 0);
|
|
36
|
+
if (flags < 0) {
|
|
37
|
+
perror("fcntl(F_GETFL)");
|
|
38
|
+
return -1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
|
42
|
+
perror("fcntl(F_SETFL)");
|
|
43
|
+
return -1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @brief Create and configure TCP server socket
|
|
51
|
+
*/
|
|
52
|
+
static int create_server_socket(uint16_t port) {
|
|
53
|
+
int sockfd;
|
|
54
|
+
struct sockaddr_in server_addr;
|
|
55
|
+
int reuse = 1;
|
|
56
|
+
|
|
57
|
+
/* Create socket */
|
|
58
|
+
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
59
|
+
if (sockfd < 0) {
|
|
60
|
+
perror("socket");
|
|
61
|
+
return -1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Set SO_REUSEADDR to reuse port immediately */
|
|
65
|
+
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
|
|
66
|
+
perror("setsockopt(SO_REUSEADDR)");
|
|
67
|
+
close(sockfd);
|
|
68
|
+
return -1;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Bind to address */
|
|
72
|
+
memset(&server_addr, 0, sizeof(server_addr));
|
|
73
|
+
server_addr.sin_family = AF_INET;
|
|
74
|
+
server_addr.sin_addr.s_addr = INADDR_ANY;
|
|
75
|
+
server_addr.sin_port = htons(port);
|
|
76
|
+
|
|
77
|
+
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
|
|
78
|
+
perror("bind");
|
|
79
|
+
close(sockfd);
|
|
80
|
+
return -1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Listen for connections */
|
|
84
|
+
if (listen(sockfd, MAX_PENDING) < 0) {
|
|
85
|
+
perror("listen");
|
|
86
|
+
close(sockfd);
|
|
87
|
+
return -1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
printf("TCP server listening on port %u\n", port);
|
|
91
|
+
return sockfd;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @brief Handle client connection
|
|
96
|
+
*/
|
|
97
|
+
static void handle_client(int client_fd, struct sockaddr_in *client_addr) {
|
|
98
|
+
char buffer[BUFFER_SIZE];
|
|
99
|
+
ssize_t bytes_read;
|
|
100
|
+
|
|
101
|
+
printf("New connection from %s:%u\n",
|
|
102
|
+
inet_ntoa(client_addr->sin_addr),
|
|
103
|
+
ntohs(client_addr->sin_port));
|
|
104
|
+
|
|
105
|
+
/* Send welcome message */
|
|
106
|
+
const char *welcome = "Welcome to TCP server!\r\n";
|
|
107
|
+
if (send(client_fd, welcome, strlen(welcome), 0) < 0) {
|
|
108
|
+
perror("send");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Echo loop */
|
|
113
|
+
while (1) {
|
|
114
|
+
bytes_read = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
|
|
115
|
+
|
|
116
|
+
if (bytes_read < 0) {
|
|
117
|
+
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
118
|
+
/* No data available, continue */
|
|
119
|
+
usleep(10000); /* 10ms */
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
perror("recv");
|
|
123
|
+
break;
|
|
124
|
+
} else if (bytes_read == 0) {
|
|
125
|
+
/* Connection closed by client */
|
|
126
|
+
printf("Client disconnected\n");
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
buffer[bytes_read] = '\0';
|
|
131
|
+
printf("Received: %s", buffer);
|
|
132
|
+
|
|
133
|
+
/* Echo back to client */
|
|
134
|
+
if (send(client_fd, buffer, bytes_read, 0) < 0) {
|
|
135
|
+
perror("send");
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Check for quit command */
|
|
140
|
+
if (strncmp(buffer, "quit", 4) == 0) {
|
|
141
|
+
printf("Client requested disconnect\n");
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @brief Main server loop
|
|
149
|
+
*/
|
|
150
|
+
int main(int argc, char *argv[]) {
|
|
151
|
+
int server_fd, client_fd;
|
|
152
|
+
struct sockaddr_in client_addr;
|
|
153
|
+
socklen_t client_len;
|
|
154
|
+
uint16_t port;
|
|
155
|
+
|
|
156
|
+
/* Parse command line arguments */
|
|
157
|
+
if (argc != 2) {
|
|
158
|
+
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
|
|
159
|
+
return EXIT_FAILURE;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
port = (uint16_t)atoi(argv[1]);
|
|
163
|
+
if (port == 0) {
|
|
164
|
+
fprintf(stderr, "Invalid port number\n");
|
|
165
|
+
return EXIT_FAILURE;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Create server socket */
|
|
169
|
+
server_fd = create_server_socket(port);
|
|
170
|
+
if (server_fd < 0) {
|
|
171
|
+
return EXIT_FAILURE;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
printf("Server started. Press Ctrl+C to stop.\n");
|
|
175
|
+
|
|
176
|
+
/* Accept connections */
|
|
177
|
+
while (1) {
|
|
178
|
+
client_len = sizeof(client_addr);
|
|
179
|
+
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
|
|
180
|
+
|
|
181
|
+
if (client_fd < 0) {
|
|
182
|
+
perror("accept");
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* Handle client (single-threaded for simplicity) */
|
|
187
|
+
handle_client(client_fd, &client_addr);
|
|
188
|
+
|
|
189
|
+
/* Close client connection */
|
|
190
|
+
close(client_fd);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* Cleanup */
|
|
194
|
+
close(server_fd);
|
|
195
|
+
return EXIT_SUCCESS;
|
|
196
|
+
}
|
|
197
|
+
|