Changeset 47d060d in mainline for uspace/srv/hid/remcons/user.c


Ignore:
Timestamp:
2024-10-04T19:23:16Z (7 days ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
c7ecd290
Parents:
5132379
Message:

Implement telnet window size option

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/remcons/user.c

    r5132379 r47d060d  
    5858static LIST_INITIALIZE(users);
    5959
     60static errno_t telnet_user_send_raw_locked(telnet_user_t *, const void *,
     61    size_t);
     62static errno_t telnet_user_flush_locked(telnet_user_t *);
     63
    6064/** Create new telnet user.
    6165 *
    6266 * @param conn Incoming connection.
     67 * @param cb Callback functions
     68 * @param arg Argument to callback functions
    6369 * @return New telnet user or NULL when out of memory.
    6470 */
    65 telnet_user_t *telnet_user_create(tcp_conn_t *conn)
     71telnet_user_t *telnet_user_create(tcp_conn_t *conn, telnet_cb_t *cb, void *arg)
    6672{
    6773        static int telnet_user_id_counter = 0;
     
    7278        }
    7379
     80        user->cb = cb;
     81        user->arg = arg;
    7482        user->id = ++telnet_user_id_counter;
    7583
     
    216224 * @return EOK on success or an error code
    217225 */
    218 static errno_t telnet_user_recv_next_byte_locked(telnet_user_t *user, char *byte)
     226static errno_t telnet_user_recv_next_byte_locked(telnet_user_t *user,
     227    uint8_t *byte)
    219228{
    220229        errno_t rc;
     
    227236        }
    228237
    229         *byte = user->socket_buffer[user->socket_buffer_pos++];
     238        *byte = (uint8_t)user->socket_buffer[user->socket_buffer_pos++];
    230239        return EOK;
    231240}
     
    241250}
    242251
    243 /** Process telnet command (currently only print to screen).
     252static errno_t telnet_user_send_opt(telnet_user_t *user, telnet_cmd_t cmd,
     253    telnet_cmd_t opt)
     254{
     255        uint8_t cmdb[3];
     256
     257        cmdb[0] = TELNET_IAC;
     258        cmdb[1] = cmd;
     259        cmdb[2] = opt;
     260
     261        return telnet_user_send_raw_locked(user, (char *)cmdb, sizeof(cmdb));
     262}
     263
     264/** Process telnet WILL NAWS command.
     265 *
     266 * @param user Telnet user structure.
     267 * @param cmd Telnet command.
     268 */
     269static void process_telnet_will_naws(telnet_user_t *user)
     270{
     271        telnet_user_log(user, "WILL NAWS");
     272        /* Send DO NAWS */
     273        (void) telnet_user_send_opt(user, TELNET_DO, TELNET_NAWS);
     274        (void) telnet_user_flush_locked(user);
     275}
     276
     277/** Process telnet SB NAWS command.
     278 *
     279 * @param user Telnet user structure.
     280 * @param cmd Telnet command.
     281 */
     282static void process_telnet_sb_naws(telnet_user_t *user)
     283{
     284        uint8_t chi, clo;
     285        uint8_t rhi, rlo;
     286        uint16_t cols;
     287        uint16_t rows;
     288        uint8_t iac;
     289        uint8_t se;
     290        errno_t rc;
     291
     292        telnet_user_log(user, "SB NAWS...");
     293
     294        rc = telnet_user_recv_next_byte_locked(user, &chi);
     295        if (rc != EOK)
     296                return;
     297        rc = telnet_user_recv_next_byte_locked(user, &clo);
     298        if (rc != EOK)
     299                return;
     300
     301        rc = telnet_user_recv_next_byte_locked(user, &rhi);
     302        if (rc != EOK)
     303                return;
     304        rc = telnet_user_recv_next_byte_locked(user, &rlo);
     305        if (rc != EOK)
     306                return;
     307
     308        rc = telnet_user_recv_next_byte_locked(user, &iac);
     309        if (rc != EOK)
     310                return;
     311        rc = telnet_user_recv_next_byte_locked(user, &se);
     312        if (rc != EOK)
     313                return;
     314
     315        cols = (chi << 8) | clo;
     316        rows = (rhi << 8) | rlo;
     317
     318        telnet_user_log(user, "cols=%u rows=%u\n", cols, rows);
     319
     320        if (cols < 1 || rows < 1) {
     321                telnet_user_log(user, "Ignoring invalid window size update.");
     322                return;
     323        }
     324
     325        user->cb->ws_update(user->arg, cols, rows);
     326}
     327
     328/** Process telnet WILL command.
     329 *
     330 * @param user Telnet user structure.
     331 * @param opt Option code.
     332 */
     333static void process_telnet_will(telnet_user_t *user, telnet_cmd_t opt)
     334{
     335        telnet_user_log(user, "WILL");
     336        switch (opt) {
     337        case TELNET_NAWS:
     338                process_telnet_will_naws(user);
     339                return;
     340        }
     341
     342        telnet_user_log(user, "Ignoring telnet command %u %u %u.",
     343            TELNET_IAC, TELNET_WILL, opt);
     344}
     345
     346/** Process telnet SB command.
     347 *
     348 * @param user Telnet user structure.
     349 * @param opt Option code.
     350 */
     351static void process_telnet_sb(telnet_user_t *user, telnet_cmd_t opt)
     352{
     353        telnet_user_log(user, "SB");
     354        switch (opt) {
     355        case TELNET_NAWS:
     356                process_telnet_sb_naws(user);
     357                return;
     358        }
     359
     360        telnet_user_log(user, "Ignoring telnet command %u %u %u.",
     361            TELNET_IAC, TELNET_SB, opt);
     362}
     363
     364/** Process telnet command.
    244365 *
    245366 * @param user Telnet user structure.
     
    250371    telnet_cmd_t option_code, telnet_cmd_t cmd)
    251372{
     373        switch (option_code) {
     374        case TELNET_SB:
     375                process_telnet_sb(user, cmd);
     376                return;
     377        case TELNET_WILL:
     378                process_telnet_will(user, cmd);
     379                return;
     380        }
     381
    252382        if (option_code != 0) {
    253383                telnet_user_log(user, "Ignoring telnet command %u %u %u.",
     
    277407
    278408        do {
    279                 char next_byte = 0;
     409                uint8_t next_byte = 0;
    280410                bool inside_telnet_command = false;
    281411
     
    290420                                return rc;
    291421                        }
    292                         uint8_t byte = (uint8_t) next_byte;
     422                        uint8_t byte = next_byte;
    293423
    294424                        /* Skip telnet commands. */
     
    296426                                inside_telnet_command = false;
    297427                                next_byte = 0;
    298                                 if (TELNET_IS_OPTION_CODE(byte)) {
     428                                if (TELNET_IS_OPTION_CODE(byte) ||
     429                                    byte == TELNET_SB) {
    299430                                        telnet_option_code = byte;
    300431                                        inside_telnet_command = true;
     
    430561}
    431562
     563static errno_t telnet_user_flush_locked(telnet_user_t *user)
     564{
     565        errno_t rc;
     566
     567        rc = tcp_conn_send(user->conn, user->send_buf, user->send_buf_used);
     568        if (rc != EOK)
     569                return rc;
     570
     571        user->send_buf_used = 0;
     572        return EOK;
     573}
     574
    432575errno_t telnet_user_flush(telnet_user_t *user)
    433576{
     
    435578
    436579        fibril_mutex_lock(&user->guard);
    437         rc = tcp_conn_send(user->conn, user->send_buf, user->send_buf_used);
    438 
    439         if (rc != EOK) {
    440                 fibril_mutex_unlock(&user->guard);
    441                 return rc;
    442         }
    443 
    444         user->send_buf_used = 0;
     580        rc = telnet_user_flush_locked(user);
    445581        fibril_mutex_unlock(&user->guard);
    446         return EOK;
     582        return rc;
    447583}
    448584
     
    467603}
    468604
     605/** Resize telnet session.
     606 *
     607 * @param user Telnet user
     608 * @param cols New number of columns
     609 * @param rows New number of rows
     610 */
     611void telnet_user_resize(telnet_user_t *user, unsigned cols, unsigned rows)
     612{
     613        user->cols = cols;
     614        user->rows = rows;
     615        if ((unsigned)user->cursor_x > cols - 1)
     616                user->cursor_x = cols - 1;
     617        if ((unsigned)user->cursor_y > rows - 1)
     618                user->cursor_y = rows - 1;
     619}
     620
    469621/**
    470622 * @}
Note: See TracChangeset for help on using the changeset viewer.