# mod_fcc **Repository Path**: jf_linux/mod_fcc ## Basic Information - **Project Name**: mod_fcc - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-14 - **Last Updated**: 2026-09-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FCC: FreeSWITCH call control for application developers FCC is released under the [MIT License](LICENSE). FCC (FreeSWITCH Call Control) exposes common call-control operations as HTTP REST and WebSocket APIs. Applications work with JSON, `call_id` values and ordered events instead of maintaining ESL connections or translating `uuid_*` and `bgapi originate` commands. Current version: `1.2.1-open`. See the [Feature and Integration Guide](docs/FUNCTION_GUIDE.md) for capabilities and production workflows, the [bilingual API reference](docs/API.md) for every endpoint, and [README.md](README.md) for Chinese documentation. > FCC is not intended to replace ESL, nor can it. Its purpose is to help developers who are new to FreeSWITCH build call center applications more quickly, with a shorter development path and a lower learning curve. If FCC helps you validate your application and you plan to scale it further, we strongly recommend learning ESL systematically to gain more flexible and in-depth control over FreeSWITCH. ## Features - Originate calls through the XML dialplan or directly through a Sofia gateway. - Register inbound calls from the dialplan and accept an API decision within a configured deadline. - Query call state and the most recent 64 events for an individual call. - Observe concurrent calls over one WebSocket, with global sequence-based resume. - Answer, pre-answer, hang up, hold/unhold, stop media, send DTMF, play a file, transfer and bridge. - Manage `mod_callcenter` callback agents: create, sign in, sign out, pause, resume, and query agent registration, queue tiers and waiting members. - Health/readiness endpoints, Prometheus metrics and Sofia profile reload. - Bearer authentication with per-source-IP failure throttling. FCC does not implement audio streaming, recording, conferencing, queues or a complete PBX. Use the FreeSWITCH dialplan and appropriate modules for those capabilities. FCC does not implement business heartbeats or infer employee presence. The backend decides when to sign in, sign out, pause or resume; FCC verifies SIP registration and translates explicit requests into `callcenter_config` operations. ## How it works FCC turns outbound requests into FreeSWITCH `bgapi originate` commands and puts `fcc_call_id` on the channel. The dialplan registers inbound calls by running `fcc_inbound`. FCC listens for progress, answer, DTMF and hangup events, keeps call state in memory, and broadcasts transitions to every WebSocket client that completed the protocol handshake. `call_id` is FCC's stable application identifier; `uuid` identifies the FreeSWITCH channel. Either value can be used in query and action paths, though applications should persist `call_id`. ## Requirements, build and install You need Linux, a C compiler, GNU Make, SQLite3 development headers (`libsqlite3-dev` on Debian/Ubuntu), and a FreeSWITCH installation with development headers and `libfreeswitch`. The default prefix is `/usr/local/freeswitch`. The FCC server implements the WebSocket protocol inside the module and does not require `libwebsockets`, OpenSSL, `mod_verto`, or another WebSocket server dependency. `scripts/install_mod_fcc.sh` only deploys the already-built module and configuration; it does not install operating-system build packages or optional Python client dependencies. ```bash cd fcc make -C freeswitch_mod FS_PREFIX=/usr/local/freeswitch FS_CLI=/usr/local/freeswitch/bin/fs_cli ./scripts/install_mod_fcc.sh ``` For a custom layout set `FS_INC_DIR`, `FS_LIB_DIR` and `FS_MOD_DIR`. The installer copies `mod_fcc.so` and `mod_fcc.conf.xml`, reloads XML, then reloads or loads the module. ## Configuration and security Edit `config/autoload_configs/mod_fcc.conf.xml` before production use, particularly: ```xml ``` For `route_mode=user`, set `default_user_domain` to the directory domain where agents register (for example, `fs.example.internal`). A request-level `user_domain` overrides this default. Keep the default loopback binding. If remote access is necessary, put FCC behind a trusted TLS reverse proxy or firewall; the module itself serves plain HTTP/WS. Every endpoint, including health checks and the WebSocket Upgrade, requires `Authorization: Bearer `. ## Quick start ```bash TOKEN='change-me' BASE='http://127.0.0.1:18080/api/v1' curl -sS -H "Authorization: Bearer $TOKEN" "$BASE/health" curl -sS -X POST "$BASE/calls" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"request_id":"order-20260803-001","caller":"1000","callee":"1001"}' curl -sS -H "Authorization: Bearer $TOKEN" "$BASE/calls/call_d8e4c390-1111-4222-8333-0123456789ab" ``` Always generate a globally unique, non-empty `request_id`. FCC atomically claims it in SQLite. The same normalized request returns the original call, while different parameters return HTTP 409 `IDEMPOTENCY_CONFLICT`. Records survive module and FreeSWITCH restarts and expire 86400 seconds after call completion by default. Empty values receive no idempotency protection. ## Routing FCC supports three route modes: - `user` builds `user/@` for a registered local extension and avoids loopback. The configured `default_user_domain` is used when omitted. - The default `dialplan` mode builds `loopback//`, preserving XML routing, number normalization and billing logic. - `direct_gateway` builds `sofia/gateway//` and bypasses XML dialplan. FreeSWITCH 1.10.12 initializes loopback with internal `L16/8000`; some SIP clients or gateways reject that offer. Prefer `user` for registered extensions and `direct_gateway` for trunks unless the downstream path is known to accept the loopback codec. A `callee` containing `/` remains a trusted complete endpoint. ```json {"request_id":"extension-001","caller":"1000","callee":"1001","route_mode":"user","user_domain":"fs.example.internal"} ``` User-mode callees accept only letters, digits, `+`, `-`, `_`, and `.` to prevent endpoint injection. Gateway example: ```json {"request_id":"out-001","caller":"1000","callee":"13800138000","route_mode":"direct_gateway","gateway":"gw_main"} ``` ## Inbound calls Register an inbound channel from the XML dialplan: ```xml ``` FCC sets `fcc_call_id`, `fcc_direction=inbound`, `fcc_service` and `fcc_register_status=registered`, then publishes `call.incoming`. The application should act before `inbound_decision_timeout_ms`. On timeout, `continue_dialplan` runs `uuid_break`; `hangup` terminates the call. ## Observing concurrent calls Maintain one WebSocket connection to `ws://127.0.0.1:18080/api/v1/ws`, passing the Bearer header during Upgrade. The first text frame must be: ```json {"type":"client.hello","request_id":"hello-1","client_id":"worker-a","protocol_version":1,"last_sequence":0} ``` Each event includes its global `sequence`, `call_id`, `uuid`, `direction` and current `status`. Keep a dictionary keyed by `call_id` and persist the highest processed sequence. Supply it as `last_sequence` after reconnecting. FCC replays up to 4096 global events; on `resume.failed` with `SEQUENCE_EXPIRED`, query known calls to rebuild state. Each client has a 1000-message outbound queue; slow clients are disconnected on overflow. FCC sends Ping every 15 seconds and disconnects after 45 seconds without Pong. A complete concurrent-call Python monitor is in the [WebSocket API section](docs/API.md#websocket-api). For a fixed-size origination pool, keep an active dictionary keyed by `call_id` and refill only after `call.hangup` removes an entry and its result is persisted. A target of 10 is an application example, not an FCC limit; the effective value depends on `max_concurrent_calls`, `max_cps`, trunk capacity, agent count, and load-test results. See the [dynamic concurrency pool guide](docs/FUNCTION_GUIDE.md#动态并发池与自动补量--dynamic-concurrency-pool-and-refill). Typical outbound state is `dialing → ringing → answered → hangup`; an unanswered termination becomes `no_answer`. Callcenter flows additionally publish `queue.joined`, `queue.agent_offered`, `queue.bridged`, `queue.bridge_ended`, `queue.abandoned`, `queue.timeout`, and `queue.completed`, all correlated to the original `call_id`. Inbound state starts at `incoming`; `decision_timeout` indicates no timely API decision. Events also include `call.dtmf`, `action.accepted`, and `action.failed`. FCC normally requires an event `Unique-ID` to match its owned UUID. A propagated DTMF event that omits `variable_fcc_call_id` can be resolved by that owned UUID; inherited loopback legs still cannot publish duplicate hangups. For calls joined through FCC `bridge`, call `hold` and `unhold` with the same customer `call_id`. FreeSWITCH plays MOH on the bridged peer. When a `uuid_bridge` call has hold flags but does not expose `Channel-Call-State=HELD`, FCC stops the peer's looping MOH and restores the existing bridge during unhold; applications do not need to pass the agent UUID. The event rings are process memory and module/FreeSWITCH restarts clear them. Non-empty idempotency mappings, UUID call IDs, and terminal call state are persisted in SQLite for the configured idempotency TTL. FCC retains 64 in-memory events per call, 4096 globally replayable events, and queryable completed records for 3600 seconds by default, bounded by `call_history_max_records`. ## Operations and tests ```bash ./tests/test_api_contract.sh FCC_SKIP_LIVE=0 FCC_API_TOKEN='your-token' ./tests/test_api_contract.sh curl -H "Authorization: Bearer $TOKEN" "$BASE/metrics" ``` `fcc_active_calls` counts calls registered with FCC that have not produced hangup-complete. The health payload also exposes `active_calls`, `max_concurrent_calls` and `max_cps`. New outbound calls return HTTP 429 when either limit is reached; inbound calls are rejected with `USER_BUSY` and `fcc_register_status=rate_limited`. Before publishing, replace the default token, retain loopback binding where possible, put remote traffic behind TLS and access controls, validate all application-provided endpoints/files/gateways/destinations, tune capacity limits, and test real inbound/outbound/DTMF/bridge/resume flows against each supported FreeSWITCH release.